【问题标题】:matchtemplate openCv2 python not match similar lookmatchtemplate openCv2 python不匹配类似的样子
【发布时间】:2020-04-29 04:04:52
【问题描述】:

我有一个随机改变颜色的图像,所以有时 OpenCV 会识别出该对象,有时却不是:

我的代码:

grey_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
grey_temp = cv2.cvtColor(temp, cv2.COLOR_BGR2GRAY)

w, h = grey_temp.shape[::-1]

res = cv2.matchTemplate(grey_img, grey_temp, cv2.TM_CCOEFF_NORMED)
print(res)

threshold = 0.8;
loc = np.where(res >= threshold)
print(loc)

for pt in zip(*loc[::-1]):
    cv2.rectangle(img, pt, (pt[0] + w, pt[1] + h), (255,0,0), 3)

cv2.imshow('win', img)
cv2.waitKey()

与 emguCv 类似的代码:

Mat background = CvInvoke.Imread(file, 
Emgu.CV.CvEnum.ImreadModes.AnyColor);//Convert Image to ReducedGrayscale2
Mat find = CvInvoke.Imread(compered, Emgu.CV.CvEnum.ImreadModes.AnyColor);
Mat match = CvInvoke.Imread(compered, Emgu.CV.CvEnum.ImreadModes.AnyColor);
CvInvoke.MatchTemplate(background, find, match, TemplateMatchingType.CcoeffNormed);         
double[] minValues, maxValues;
Point[] minLocations, maxLocations;
match.MinMax(out minValues, out maxValues, out minLocations, out maxLocations);
            if (maxValues[0] > 0.7)
            {
                Console.WriteLine("found");
                Rectangle match1 = new Rectangle(maxLocations[0],);
                match.Draw(match1, new Bgr(Color.Red), 3);
            }

        CvInvoke.Imshow("Image1", background);
        CvInvoke.WaitKey(0);

(顺便说一句,更改阈值没有贡献)

识别示例:

我想知道你是否知道如何在不依赖颜色、灰度或他的位置的情况下跟踪照片中的相同图案对象(该对象具有一些相似的共享属性,因此在人眼中它称为易于跟踪)。

我尝试使用 emguCv for c sharp 进行相同的进度,以检查结果是否有任何不同,但没有意外,没有区别。 如果您能建议我如何管理以跟踪主图像中的模板,我将不胜感激。 提前致谢!

【问题讨论】:

  • 蓝色图像中没有您的粉色模板,因此不匹配。您不应该先转换为灰度。 matchTemplate() 可以处理彩色图像。在不知道位置并且至少不使用灰度值的情况下要求跟踪是没有意义的。如果你想要颜色独立而不是模板匹配,那么就有了特征匹配。但是没有锐角和其他纹理的平滑变化的图像将很难找到足够的特征来使用。也许其他人可能对您有其他想法。
  • @fmw42 谢谢你。你有什么建议我可以教我的电脑注意类似的模板吗?
  • 我可以建议的最佳想法是转换为灰度,从 sobel 和阈值或 Canny 边缘提取边缘。然后在二进制边缘图像上进行模板匹配。

标签: c# python opencv emgucv matchtemplate


【解决方案1】:

一种颜色不敏感的方法是对二值边缘提取图像进行模板匹配。所以这似乎适用于 Python/OpenCV。

  • 将图像和模板读取为灰度
  • 使用 L2gradient=True 进行 Canny 边缘检测
  • 对这些边缘图像进行归一化互相关
  • 获取最大相关值的位置
  • 将模板白色边缘以红色放入图像边缘

图片:

模板:

import cv2
import numpy as np

# read image
img = cv2.imread('blue_object.png')

# convert img to grayscale
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# read template as grayscale
tmplt = cv2.imread('pink_template.png', cv2.IMREAD_GRAYSCALE)
hh, ww = tmplt.shape

# do canny edge detection on image and template
img_edges = cv2.Canny(img_gray,100,200,3,L2gradient=True)
tmplt_edges = cv2.Canny(tmplt,100,200,3,L2gradient=True)

# do template matching
corrimg = cv2.matchTemplate(img_edges,tmplt_edges,cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(corrimg)
max_val_ncc = '{:.3f}'.format(max_val)
print("normalize_cross_correlation: " + max_val_ncc)
xx = max_loc[0]
yy = max_loc[1]
print('xmatchloc =',xx,'ymatch =',yy)

# offset the templt_edges image to place at match point in black image the size of the img_edges
templt_edges_match = np.full_like(img_edges, 0)
templt_edges_match[yy:yy+hh, xx:xx+ww] = tmplt_edges

# draw template edges in red onto img edges
result1 = img_edges.copy()
result1 = cv2.merge((result1, result1, result1))
result1[templt_edges_match==255] = (0,0,255)

# draw template edges in red onto img
result2 = img.copy()
result2[templt_edges_match==255] = (0,0,255)

cv2.imshow('image', img)
cv2.imshow('template', tmplt)
cv2.imshow('image edges', img_edges)
cv2.imshow('template edges', tmplt_edges)
cv2.imshow('result1', result1)
cv2.imshow('result2', result2)
cv2.waitKey(0)
cv2.destroyAllWindows()

# save results
cv2.imwrite('edge_template_match_on_image_edges.png', result1)
cv2.imwrite('edge_template_match_on_image.png', result2)


结果1:

结果2:

比赛地点:

xmatchloc = 59 ymatch = 36

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-26
    • 1970-01-01
    • 1970-01-01
    • 2021-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多