OpenCV边界检测并获取物体边缘坐标范围
目前在用YOLO识别物体,遇到一个场景是有多个同样的物体,但要通过另一个参照物来区分。而参照物的位置和特征并不相同,于是考虑到了使用边界检测,只要在同一区域内,便可方便灵活地标识出唯一物体。
比如我用当前网站的首页来做个例子:
这里对于人眼来说,是能看到明显的区域的概念。比如我实际想找的是'继续阅读'的按钮,但是如果用标题和距离来限定,很容易将一个按钮和下面的标题混合起来,如果要找的东西又在中间,则上下都可能混合。因此可以划分边界,从区域内去匹配。
比如常用的有Laplacian, 这里先做高斯滤波降噪,然后用拉普拉斯算子检测边缘,用numpy取出了非0的即为边缘点:
img = cv2.imread('./home.png', cv2.IMREAD_GRAYSCALE)
gaussian = cv2.GaussianBlur(img, (3, 3), 0)
dst = cv2.Laplacian(gaussian, cv2.CV_16S, ksize=3)
cv_img = cv2.convertScaleAbs(dst)
indices = np.where(cv_img != [0])
coordinates = zip(indices[0], indices[1])
for c in coordinates:
print(c)
另外Canny也是常见的:
img = cv2.imread('./home.png', cv2.IMREAD_GRAYSCALE)
gaussian_blur = cv2.GaussianBlur(img, (3, 3), 0)
cv_Canny = cv2.Canny(gaussian_blur, 100, 200)
效果可以用imwrite或imshow能看到。
边缘倒是大致勾勒出来了,但是需要的是一个坐标范围,这样才能计算参照物和目标物体。
于是改成如下的:
import cv2
import numpy as np
image = cv2.imread('./home.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# Sharpen the image
kernel = np.array([[-1, -1, -1], [-1, 8, -1], [-1, -1, 0]], np.float32)
dst = cv2.filter2D(gray, -1, kernel)
# Canny Edge detection
canny = cv2.Canny(dst, 30, 200, 1)
# Find contours
cnts = cv2.findContours(canny, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2:]
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
# Iterate thorugh contours and draw rectangles around contours
cnts.reverse()
for c in cnts:
x, y, w, h = cv2.boundingRect(c)
cv2.rectangle(image, (x, y), (x + w, y + h), (255, 0, 255), 1)
cv2.imwrite('./home-edge.png', image)
在这里保存的图像能看到在原图上勾勒出的边缘,其中x / y / w / h便是范围了。如下图:
在这里也能看到一个问题,就是边缘太多了,而且有的是因为文字非常细,并不是需要的。
那么加一个判断即可
if w > 100 and h > 100:
cv2.rectangle(image, (x, y), (x + w, y + h), (255, 0, 255), 1)
如下图:
此时便可归纳参照物和目标物体了。
参考链接:
下一篇:
Mac M1重装环境问题汇总