Python OpenCV模板匹配和特征检测无法正常工作

nvbavucw  于 2023-10-24  发布在  Python
关注(0)|答案(1)|浏览(121)

我尝试使用模板识别图像中的特定形状。我通过添加两颗星星来编辑原始图像。现在,我尝试检测这些星星的位置,但它似乎无法识别它们。我使用了两种方法,模板匹配和特征检测,但都没有产生预期的结果。
我的主要目标是成功地检测到两颗恒星,并将它们连接起来形成一个矩形,最终在新图像中为我提供答案区域。然而,我最初的重点是准确地检测标记。
基本图像和模板如下所示:

首先,我尝试将图像与模板相匹配。

# Load the base image and the black star image
base_image = cv2.imread(path_saida_jpg, cv2.IMREAD_COLOR)
star_template = cv2.imread(path_base_star, cv2.IMREAD_COLOR)

base_gray = cv2.cvtColor(base_image, cv2.COLOR_BGR2GRAY)
star_template_gray = cv2.cvtColor(star_template, cv2.COLOR_BGR2GRAY)

# Perform template matching to find the stars
result = cv2.matchTemplate(base_image, star_template, cv2.TM_CCOEFF_NORMED)
threshold = 0.80  
locations = np.where(result >= threshold)

# Draw rectangles around the found stars
for loc in zip(*locations[::-1]):
    h, w = star_template.shape[:2]
    cv2.rectangle(base_image, loc, (loc[0] + w, loc[1] + h), (0, 255, 0), 2)  # Draw a green rectangle

    cv2.imwrite('result_image.jpg', base_image)

位置总是空的,该软件作为只有能够找到一些匹配时,我降低阈值变量为0.6.但结果不是预期.这里是:

后来,我意识到这个问题可能与规模有关。因此,我尝试使用ORB的特征检测和匹配来解决这个问题(定向FAST和旋转BRIEF)。在我最初的尝试中,当使用原始比例(64px)的模板图像时,我没有得到任何结果。因此,我决定将其大小增加到512px,希望提高成功的机会。令人惊讶的是,结果更不理想。下面是代码和结果输出:

base_image = cv2.imread(path_saida_jpg, cv2.IMREAD_COLOR)
star_template = cv2.imread(path_base_star, cv2.IMREAD_COLOR)

base_gray = cv2.cvtColor(base_image, cv2.COLOR_BGR2GRAY)
star_template_gray = cv2.cvtColor(star_template, cv2.COLOR_BGR2GRAY)

orb = cv2.ORB_create()

kp1, des1 = orb.detectAndCompute(base_gray, None)
kp2, des2 = orb.detectAndCompute(star_template_gray, None)
 
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)

matches = bf.match(des1, des2)

matches = sorted(matches, key=lambda x: x.distance)

result_image = cv2.drawMatches(base_image, kp1, star_template, kp2, matches[:10], None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)

# Export the result
cv2.imwrite('result_image.jpg', result_image)

有人有什么建议吗?我是图像处理领域的新手,在这个复杂的任务中我发现自己有点迷失方向。我一直在使用ChatGPT和来自GeeksforGeeks的资源来帮助我。

zphenhs4

zphenhs41#

我已经从你的图像中裁剪了你的星星作为Python/OpenCV模板匹配的模板。然后我使用一种在循环中屏蔽相关图像的技术来找到两个匹配。在搜索下一个顶部匹配之前,每个顶部匹配在TM_CCORR_NORMED(归一化互相关)表面中用零屏蔽。

  • 读取输入
  • 阅读模板
  • 设置参数
  • 计算TM_CCORR_NORMED图像
  • 循环匹配,如果max_瓦尔> match_threshold,保存相关位置和值并屏蔽相关图像。然后重复,直到max_瓦尔低于match_thresh。
  • 保存结果

输入:

模板(T):

import cv2
import numpy as np

# read image
img = cv2.imread('prova_da_epcar.jpg')

# read template
tmplt = cv2.imread('star.png')
hh, ww, cc = tmplt.shape

# set arguments
match_thresh = 0.95               # stopping threshold for match value
num_matches = 10                  # stopping threshold for number of matches
match_radius = max(hh,ww)//4      # approx radius of match peaks

# get correlation surface from template matching
corrimg = cv2.matchTemplate(img,tmplt,cv2.TM_CCORR_NORMED)
hc, wc = corrimg.shape

# get locations of all peaks higher than match_thresh for up to num_matches
imgcopy = img.copy()
corrcopy = corrimg.copy()
for i in range(1, num_matches):
    # get max value and location of max
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(corrcopy)
    x1 = max_loc[0]
    y1 = max_loc[1]
    x2 = x1 + ww
    y2 = y1 + hh
    loc = str(x1) + "," + str(y1)
    if max_val > match_thresh:
        print("match number:", i, "match value:", max_val, "match x,y:", loc)
        # draw draw blue bounding box to define match location
        cv2.rectangle(imgcopy, (x1,y1), (x2,y2), (0,0,255), 2)
        # draw black filled circle over copy of corrimg 
        cv2.circle(corrcopy, (x1,y1), match_radius, 0, -1)
        # faster alternate - insert black rectangle
        # corrcopy[y1:y2, x1:x2] = 0
        i = i + 1
    else:
        break
    
# save results
# power of 4 exaggeration of correlation image to emphasize peaks
cv2.imwrite('prova_da_epcar_corr.png', (255*cv2.pow(corrimg,4)).clip(0,255).astype(np.uint8))
cv2.imwrite('prova_da_epcar_star_corr_masked.png', (255*cv2.pow(corrcopy,4)).clip(0,255).astype(np.uint8))
cv2.imwrite('prova_da_epcar_star_multi_match.png', imgcopy)

# show results
# power of 4 exaggeration of correlation image to emphasize peaks
cv2.imshow('image', img)
cv2.imshow('template', tmplt)
cv2.imshow('corr', cv2.pow(corrimg,4))
cv2.imshow('corr masked', cv2.pow(corrcopy,4))
cv2.imshow('result', imgcopy)
cv2.waitKey(0)
cv2.destroyAllWindows()

相关图像:

最终掩蔽相关图像:

测试结果:

我建议你在将来的图片中使用3到4个符号来帮助你的图片稍微旋转。你也可以考虑使用一个环作为你的符号来独立于旋转。
我还建议您使用cv2.TM_CCORR_NORMED(或cv2.TM_SQUER_NORMED和带白色的遮罩)而不是cv2.TM_CCOEF_NORMED
也有non-maxima suppression方法用于检测不需要屏蔽的多个匹配。参见example

相关问题