如何在opencv中的图像中找到形状的角点?

r_r*_*jan 3 opencv image image-processing edge-detection corner-detection

我必须在图像中找到形状的角。我已经使用哈里斯角点检测算法来找到角点,但是它给出了图像中存在的总角点,并且无法为该图像中的特定形状找到角点。请提出其他建议。在此处输入图片说明

kav*_*vko 8

您可以使用Harris角点检测算法。角是两个边缘的交汇点,其中边缘是图像亮度的突然变化。该算法直接参考方向将角点得分的差异考虑在内(维基百科)。函数cornerSubPix()改进了角的位置-进行迭代以找到角或径向鞍点的子像素的精确位置(opencv文档)。

代码示例:

import cv2
import numpy as np


img = cv2.imread('edges.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = np.float32(gray)
dst = cv2.cornerHarris(gray,5,3,0.04)
ret, dst = cv2.threshold(dst,0.1*dst.max(),255,0)
dst = np.uint8(dst)
ret, labels, stats, centroids = cv2.connectedComponentsWithStats(dst)
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 100, 0.001)
corners = cv2.cornerSubPix(gray,np.float32(centroids),(5,5),(-1,-1),criteria)
for i in range(1, len(corners)):
    print(corners[i])
img[dst>0.1*dst.max()]=[0,0,255]
cv2.imshow('image', img)
cv2.waitKey(0)
cv2.destroyAllWindows
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

在此处输入图片说明

检查它们是否是真实值,您可以添加:

for i in range(1, len(corners)):
    print(corners[i,0])
    cv2.circle(img, (int(corners[i,0]), int(corners[i,1])), 7, (0,255,0), 2)
Run Code Online (Sandbox Code Playgroud)

结果:

在此处输入图片说明

编辑:

如果要为每种形状分别提取角,可以先搜索轮廓,然后对每个轮廓应用Harris角检测(可以使用cv2.fillPolly()将其绘制在蒙版上)。您甚至可以根据其特征(例如旋转角度,拐角数量等)定义它们的形状。我已经编写了一个示例代码来帮助您理解,但请注意,还有其他形状可以符合我制定的标准,而您也可以制定其他标准(梯形,圆形等)。这只是一个简单的例子:

import cv2
import numpy as np


img = cv2.imread('edges.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(gray,150,255,cv2.THRESH_BINARY)
im2, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)

for i in contours:
    img = cv2.imread('edges.png')
    size = cv2.contourArea(i)
    rect = cv2.minAreaRect(i)
    if size <10000:
        gray = np.float32(gray)
        mask = np.zeros(gray.shape, dtype="uint8")
        cv2.fillPoly(mask, [i], (255,255,255))
        dst = cv2.cornerHarris(mask,5,3,0.04)
        ret, dst = cv2.threshold(dst,0.1*dst.max(),255,0)
        dst = np.uint8(dst)
        ret, labels, stats, centroids = cv2.connectedComponentsWithStats(dst)
        criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 100, 0.001)
        corners = cv2.cornerSubPix(gray,np.float32(centroids),(5,5),(-1,-1),criteria)
        if rect[2] == 0 and len(corners) == 5:
            x,y,w,h = cv2.boundingRect(i)
            if w == h or w == h +3: #Just for the sake of example
                print('Square corners: ')
                for i in range(1, len(corners)):
                    print(corners[i])
            else:
                print('Rectangle corners: ')
                for i in range(1, len(corners)):
                    print(corners[i])
        if len(corners) == 5 and rect[2] != 0:
            print('Rombus corners: ')
            for i in range(1, len(corners)):
                print(corners[i])
        if len(corners) == 4:
            print('Triangle corners: ')
            for i in range(1, len(corners)):
                print(corners[i])
        if len(corners) == 6:
            print('Pentagon corners: ')
            for i in range(1, len(corners)):
                print(corners[i])
        img[dst>0.1*dst.max()]=[0,0,255]
        cv2.imshow('image', img)
        cv2.waitKey(0)
        cv2.destroyAllWindows
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

输出(检测到所有形状之后):

在此处输入图片说明

  • 感谢您的反馈。我不会写太多,因为我的英语不太好。努力介绍了这些功能。干杯 (3认同)
  • 如果您能简要介绍一下 `cv2.cornerSubPix()` 和 `cv2.cornerHarris()` 的作用,那么这个答案将是完美的;考虑到有人遇到这个答案是外行。很好的答案!+1 !! (2认同)
  • 从不回避尝试。如果有一些错误有人会帮助编辑它!好功夫 ! (2认同)

小智 0

对于每个形状,跟踪轮廓,并对于轮廓的每个像素,检查是否找到附近的角点(例如在 3x3 或 5x5 邻域中)。