这是一种利用浮雕/凹陷图像的凹陷和凸起轮廓的方法。主要思想是:
- 将图像转换为灰度
- 执行形态转换
- 使用 Canny 边缘检测找到轮廓
- 扩大 canny 图像以将单个轮廓合并为单个轮廓
- 执行轮廓检测以找到上/下半部分的 ROI 维度
- 获取顶部/底部 canny 图像的 ROI
- 计算每一半的非零数组元素
转为灰度并进行形态学变换
执行精明的边缘检测以找到轮廓。确定一个物体是否有凸起/凹陷的关键是比较精巧的边缘。方法如下:我们观察物体,如果它的上半部分比下半部分有更多的轮廓/线条/像素,那么它就是凹陷的。同样,如果上半部分的像素少于下半部分的像素,那么它就是浮雕的。
现在我们有了精巧的边缘,我们调整图像直到所有轮廓都连接起来,这样我们就得到了一个单一的对象。
然后我们执行轮廓检测以获得对象的ROI
从这里开始,我们将每个对象分为顶部和底部
现在我们有了顶部和底部的 ROI,我们在 canny 图像中裁剪 ROI
对于每一半,我们使用 cv2.countNonZero()
计算非零数组元素.对于浮雕对象,我们得到这个
('top', 1085)
('bottom', 1899)
对于凹陷的物体,我们得到这个
('top', 979)
('bottom', 468)
因此,通过比较两半之间的值,如果上半部分的像素少于下半部分,则它是浮雕的。如果它有更多,它就会凹陷。
import numpy as np
import cv2
original_image = cv2.imread("1.jpg")
image = original_image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))
morph = cv2.morphologyEx(gray, cv2.MORPH_OPEN, kernel)
canny = cv2.Canny(morph, 130, 255, 1)
# Dilate canny image so contours connect and form a single contour
dilate = cv2.dilate(canny, kernel, iterations=4)
cv2.imshow("morph", morph)
cv2.imshow("canny", canny)
cv2.imshow("dilate", dilate)
# Find contours in the image
cnts = cv2.findContours(dilate.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
contours = []
# For each image separate it into top/bottom halfs
for c in cnts:
# Obtain bounding rectangle for each contour
x,y,w,h = cv2.boundingRect(c)
# Draw bounding box rectangle
cv2.rectangle(original_image,(x,y),(x+w,y+h),(0,255,0),3)
# cv2.rectangle(original_image,(x,y),(x+w,y+h/2),(0,255,0),3) # top
# cv2.rectangle(original_image,(x,y+h/2),(x+w,y+h),(0,255,0),3) # bottom
top_half = ((x,y), (x+w, y+h/2))
bottom_half = ((x,y+h/2), (x+w, y+h))
# Collect top/bottom ROIs
contours.append((top_half, bottom_half))
for index, c in enumerate(contours):
top_half, bottom_half = c
top_x1,top_y1 = top_half[0]
top_x2,top_y2 = top_half[1]
bottom_x1,bottom_y1 = bottom_half[0]
bottom_x2,bottom_y2 = bottom_half[1]
# Grab ROI of top/bottom section from canny image
top_image = canny[top_y1:top_y2, top_x1:top_x2]
bottom_image = canny[bottom_y1:bottom_y2, bottom_x1:bottom_x2]
cv2.imshow('top_image', top_image)
cv2.imshow('bottom_image', bottom_image)
# Count non-zero array elements
top_pixels = cv2.countNonZero(top_image)
bottom_pixels = cv2.countNonZero(bottom_image)
print('top', top_pixels)
print('bottom', bottom_pixels)
cv2.imshow("detected", original_image)
print('contours detected: {}'.format(len(contours)))
cv2.waitKey(0)
我是一名优秀的程序员,十分优秀!