此示例显示由cv.BinaryDescriptorMatcher类提供的行描述符匹配的功能。
此模块显示如何通过2种不同的方法从图像中提取线段:首先使用线段检测器cv.LSDDetector对线进行分段,然后(或仅使用)使用二进制描述符获取线并为它们提供描述符cv.BinaryDescriptor。最后,我们可以使用cv.BinaryDescriptorMatcher类匹配线段。
资料来源:
内容
描述符之间的匹配
如果我们从两个不同的图像中提取了描述符,则可以在它们之间搜索匹配。一种方法是将描述符与每个输入查询描述符完全匹配,选择最近距离的描述符。
有时,我们可能有兴趣搜索最接近的k描述符,给定一个输入。请参见cv.BinaryDescriptorMatcher.knnMatch
在某些情况下,我们可以有一个搜索半径,看看远处的最重要的描述符[R从输入查询。请参阅cv.BinaryDescriptorMatcher.radiusMatch
图片
<span style="color:#000000">
<span style="color:#0000ff">如果为</span> false,<span style="color:#228b22">%load images</span>
img1 = cv.imread(fullfile(mexopencv.root(),<span style="color:#a020f0">'test'</span>,<span style="color:#a020f0">'books_left.jpg'</span>),<span style="color:#a020f0">'Color'</span>,true);
img2 = cv.imread(fullfile(mexopencv.root(),<span style="color:#a020f0">'test'</span>,<span style="color:#a020f0">'books_right.jpg'</span>),<span style="color:#a020f0">'Color'</span>,true);
<span style="color:#0000ff">否则</span>
im = which(<span style="color:#a020f0">'cameraman.tif'</span>);
<span style="color:#0000ff">if</span> isempty(im),im = fullfile(mexopencv.root(),<span style="color:#a020f0">'test'</span>,<span style="color:#a020f0">'blox.jpg'</span>); <span style="color:#0000ff">结束</span>
img1 = cv.imread(im,<span style="color:#a020f0">'Color'</span>,true);
M = cv.getRotationMatrix2D(round([size(img1,2)size(img1,1)] ./ 2), - 20,0.9);
img2 = cv.warpAffine(img1,M);
<span style="color:#0000ff">结束</span>
<span style="color:#228b22">%创建二进制掩码</span>
mask1 = ones(size(img1,1),size(img1,2),<span style="color:#a020f0">'uint8'</span>);
mask2 = ones(size(img2,1),size(img2,2),<span style="color:#a020f0">'uint8'</span>);
subplot(121),imshow(img1)
subplot(122),imshow(img2)
img <span style="color:#a020f0">img1 </span> <span style="color:#a020f0">img2 </span> <span style="color:#a020f0">mask1 </span> <span style="color:#a020f0">mask2</span></span>
<span style="color:#4c4c4c"> 名称大小字节类属性
img1 256x256x3 196608 uint8
img2 256x256x3 196608 uint8
mask1 256x256 65536 uint8
mask2 256x256 65536 uint8
</span>
BinaryDescriptor:检测和计算
<span style="color:#000000"><span style="color:#228b22">%使用默认参数创建BinaryDescriptor对象</span>
bd = cv.BinaryDescriptor();
<span style="color:#228b22">%compute lines and descriptors</span>
[keylines1,descr1] = bd.detectAndCompute(img1,<span style="color:#a020f0">'Mask'</span>,mask1);
[keylines2,descr2] = bd.detectAndCompute(img2,<span style="color:#a020f0">'Mask'</span>,mask2);
卫生组织<span style="color:#a020f0">keylines1 </span> <span style="color:#a020f0">keylines2 </span> <span style="color:#a020f0">descr1 </span> <span style="color:#a020f0">descr2</span>
<span style="color:#228b22">%从第一个八度音程中选择keylines及其描述符</span>
idx =([keylines1.octave] == 0);
keylines1 = keylines1(idx);
descr1 = descr1(idx,:);
idx =([keylines2.octave] == 0);
keylines2 = keylines2(idx);
descr2 = descr2(idx,:);</span>
<span style="color:#4c4c4c"> 名称大小字节类属性
descr1 53x32 1696 uint8
descr2 46x32 1472 uint8
keylines1 1x53 79208 struct
keylines2 1x46 68848 struct
</span>
BinaryDescriptor:匹配
<span style="color:#000000"><span style="color:#228b22">%创建BinaryDescriptorMatcher对象</span>
bdm = cv.BinaryDescriptorMatcher();
<span style="color:#228b22">%需要匹配</span>
matches = bdm.match(descr1,descr2)
<span style="color:#228b22">%选择最佳匹配</span>
MATCHES_DIST_THRESHOLD = 25;
good_matches =([matches.distance] <MATCHES_DIST_THRESHOLD);
fprintf(<span style="color:#a020f0">'匹配数=%d \ n'</span>,nnz(good_matches));
<span style="color:#228b22">%plot匹配</span>
outImg = cv.drawLineMatches(img1,keylines1,img2,keylines2,matches,<span style="color:#0000ff">... </span>
<span style="color:#a020f0">'MatchesMask'</span>,good_matches);
图,imshow(outImg)
标题(<span style="color:#a020f0">'八度音阶0'</span>)</span>
<span style="color:#4c4c4c">匹配=
带字段的1×53结构数组:
queryIdx
trainIdx
imgIdx
距离
好的比赛数= 12
</span>
LSDDetector:检测和计算
<span style="color:#000000"><span style="color:#228b22">%创建一个LSD检测器</span>
lsd = cv.LSDDetector();
<span style="color:#228b22">%检测行</span>
keylines1 = lsd.detect(img1,<span style="color:#a020f0">'Scale'</span>,2,<span style="color:#a020f0">'NumOctaves'</span>,2,<span style="color:#a020f0">'Mask'</span>,mask1);
keylines2 = lsd.detect(img2,<span style="color:#a020f0">'Scale'</span>,2,<span style="color:#a020f0">'NumOctaves'</span>,2,<span style="color:#a020f0">'Mask'</span>,mask2);
卫生组织<span style="color:#a020f0">keylines1 </span> <span style="color:#a020f0">keylines2</span>
<span style="color:#228b22">行的%计算描述符</span>
descr1 = bd.compute(img1,keylines1);
descr2 = bd.compute(img2,keylines2);
卫生组织<span style="color:#a020f0">descr1 </span> <span style="color:#a020f0">descr2</span>
<span style="color:#228b22">%从第二个八度音程中选择行和描述符</span>
idx =([keylines1.octave] == 1);
keylines1 = keylines1(idx);
descr1 = descr1(idx,:);
idx =([keylines2.octave] == 1);
keylines2 = keylines2(idx);
descr2 = descr2(idx,:);</span>
<span style="color:#4c4c4c"> 名称大小字节类属性
keylines1 1x230 341168结构
keylines2 1x208 308608 struct
名称大小字节类属性
descr1 230x32 7360 uint8
descr2 208x32 6656 uint8
</span>
LSDDetector:匹配
<span style="color:#000000"><span style="color:#228b22">%compute匹配</span>
matches = bdm.match(descr1,descr2)
<span style="color:#228b22">%选择最佳匹配</span>
good_matches =([matches.distance] <MATCHES_DIST_THRESHOLD);
fprintf(<span style="color:#a020f0">'匹配数=%d \ n'</span>,nnz(good_matches));
<span style="color:#228b22">%情节匹配</span>
img1 = cv.resize(img1,0.5,0.5);
img2 = cv.resize(img2,0.5,0.5);
outImg = cv.drawLineMatches(img1,keylines1,img2,keylines2,matches,<span style="color:#0000ff">... </span>
<span style="color:#a020f0">'MatchesMask'</span>,good_matches);
图,imshow(outImg)
标题(<span style="color:#a020f0">'LSD匹配八度音阶'</span>)</span>
<span style="color:#4c4c4c">匹配=
带字段的1×64结构数组:
queryIdx
trainIdx
imgIdx
距离
好匹配数= 16
</span>