乍看之下,人眼有4个角。但是在计算机视觉中,拐角被认为是在其整个邻域中强度梯度变化较大的点。邻域可以是4像素邻域或8像素邻域。
在提供的用于找到强度梯度的方程式中,已考虑将其用于4像素邻域SEE DOCUMENTATION 。
这是我要处理的图像的方法。我也有python中的代码:
path = r'C:\Users\selwyn77\Desktop\Stack\corner'
filename = 'env.jpg'
img = cv2.imread(os.path.join(path, filename))
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #--- convert to grayscale
始终模糊图像以消除可能的渐变变化并保留更强烈的渐变是一个不错的选择。我选择选择双边滤波器 ,该滤波器与高斯滤波器不同,它不会模糊附近的所有像素。而是模糊具有与中心像素相似的像素强度的像素。简而言之,它保留了高梯度变化的边缘/角,但模糊了具有最小梯度变化的区域。
bi = cv2.bilateralFilter(gray, 5, 75, 75)
cv2.imshow('bi',bi)
对于人类而言,与原始图像相比并没有太大的区别。但这很重要。现在找到可能的角落:
dst = cv2.cornerHarris(bi, 2, 3, 0.04)
dst
返回一个数组(图像的2D形状相同),该数组具有从此处提到的最终方程式获得的特征值。
现在必须应用阈值来选择那些超出特定值的角。我将在文档中使用一个:
#--- create a black image to see where those corners occur ---
mask = np.zeros_like(gray)
#--- applying a threshold and turning those pixels above the threshold to white ---
mask[dst>0.01*dst.max()] = 255
cv2.imshow('mask', mask)
白色像素是可能的角区域。您会发现彼此相邻的许多角。
要在图像上绘制选定的角:
img[dst > 0.01 * dst.max()] = [0, 0, 255] #--- [0, 0, 255] --> Red ---
cv2.imshow('dst', img)
(红色像素是角落,不太明显)
为了得到带有角的所有像素的数组:
coordinates = np.argwhere(mask)
更新
变量coor
是一个数组数组。将其转换为列表列表
coor_list = [l.tolist() for l in list(coor)]
将上面的转换为元组列表
coor_tuples = [tuple(l) for l in coor_list]
我有一种简单而又幼稚的方法来找到4个角。我只是简单地计算了每个角到另一个角的距离。我保留了距离超过一定阈值的那些角。
这是代码:
thresh = 50
def distance(pt1, pt2):
(x1, y1), (x2, y2) = pt1, pt2
dist = math.sqrt( (x2 - x1)**2 + (y2 - y1)**2 )
return dist
coor_tuples_copy = coor_tuples
i = 1
for pt1 in coor_tuples:
print(' I :', i)
for pt2 in coor_tuples[i::1]:
print(pt1, pt2)
print('Distance :', distance(pt1, pt2))
if(distance(pt1, pt2) < thresh):
coor_tuples_copy.remove(pt2)
i+=1
在运行片段之前, coor_tuples
具有所有拐角点: [(4, 42), (4, 43), (5, 43), (5, 44), (6, 44), (7, 219), (133, 36), (133, 37), (133, 38), (134, 37), (135, 224), (135, 225), (136, 225), (136, 226), (137, 225), (137, 226), (137, 227), (138, 226)]
coor_tuples
[(4, 42), (4, 43), (5, 43), (5, 44), (6, 44), (7, 219), (133, 36), (133, 37), (133, 38), (134, 37), (135, 224), (135, 225), (136, 225), (136, 226), (137, 225), (137, 226), (137, 227), (138, 226)]
coor_tuples
[(4, 42), (4, 43), (5, 43), (5, 44), (6, 44), (7, 219), (133, 36), (133, 37), (133, 38), (134, 37), (135, 224), (135, 225), (136, 225), (136, 226), (137, 225), (137, 226), (137, 227), (138, 226)]
coor_tuples
[(4, 42), (4, 43), (5, 43), (5, 44), (6, 44), (7, 219), (133, 36), (133, 37), (133, 38), (134, 37), (135, 224), (135, 225), (136, 225), (136, 226), (137, 225), (137, 226), (137, 227), (138, 226)]
coor_tuples
[(4, 42), (4, 43), (5, 43), (5, 44), (6, 44), (7, 219), (133, 36), (133, 37), (133, 38), (134, 37), (135, 224), (135, 225), (136, 225), (136, 226), (137, 225), (137, 226), (137, 227), (138, 226)]
coor_tuples
[(4, 42), (4, 43), (5, 43), (5, 44), (6, 44), (7, 219), (133, 36), (133, 37), (133, 38), (134, 37), (135, 224), (135, 225), (136, 225), (136, 226), (137, 225), (137, 226), (137, 227), (138, 226)]
coor_tuples
[(4, 42), (4, 43), (5, 43), (5, 44), (6, 44), (7, 219), (133, 36), (133, 37), (133, 38), (134, 37), (135, 224), (135, 225), (136, 225), (136, 226), (137, 225), (137, 226), (137, 227), (138, 226)]
运行代码段后,我剩下了四个角:
[(4, 42), (7, 219), (133, 36), (135, 224)]
更新2
现在您所要做的只是在原始图像的副本上标记这4个点。
img2 = img.copy()
for pt in coor_tuples:
cv2.circle(img2, tuple(reversed(pt)), 3, (0, 0, 255), -1)
cv2.imshow('Image with 4 corners', img2)
0
我正在尝试查找图像上的角,我不需要轮廓,只需要4个角。我将使用4个角更改视角。
我正在使用Opencv,但是我需要知道查找拐角的步骤以及将使用的功能。
我的图像将是这样的:(没有红色点,以后我会画点)
编辑:
按照建议的步骤操作后,我编写了代码:(注意:我不是使用纯OpenCv,而是使用javaCV,但是逻辑上是相同的)。
因此,我想找到角落,但是我不知道如何使用cvCornerHarris等拐角功能。