记录准研一小白第一次动手实践课题组师姐安排的任务,非常感谢CSDN前辈们所撰写的博客对我的帮助。 一、项目背景
如图所示,有这样一张现场勘测的图片,要实现绘制出图中三个黄色标记块的最小矩形框以及左上角的坐标点
二、研究思路 读取图片——>提取图中黄色部分——>腐蚀操作剔除细小轮廓——>查找所有轮廓——>筛选并绘制出符合条件的轮廓——>绘制最小矩形框并标记出坐标 三、代码实现 读取图片代码如下:
image = cv2.imread(img_path)
print(image.shape)
height, width, channel = image.shape
image = cv2.resize(image, (int(0.125*width), int(0.125*height)), interpolation=cv2.INTER_CUBIC)
cv2.imshow("original", image)
提取图片黄色区域代码如下:
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
low_hsv = np.array([26,43,46])
high_hsv = np.array([34,255,255])
mask = cv2.inRange(hsv,lowerb=low_hsv,upperb=high_hsv)
cv2.imshow("find_yellow",mask)
可以通过比照HSV的参考表,获取所需要提取颜色的相应范围
通过腐蚀操作剔除一系列细小轮廓代码如下:
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
mask = cv2.erode(mask, kernel,15)
cv2.imshow("morphology", mask)
可以发现经过此操作后得到的图像明显干净了很多 查找所有轮廓的代码如下:
contours, hierarchy = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
print("find", len(contours), "contours")
def drawMyContours(winName, image, contours, draw_on_blank):
if (draw_on_blank):
temp = np.ones(image.shape, dtype=np.uint8) * 255
cv2.drawContours(temp, contours, -1, (0, 0, 0), 2)
else:
temp = image.copy()
cv2.drawContours(temp, contours, -1, (0, 0, 255), 2)
cv2.imshow(winName, temp)
drawMyContours("find contours", image, contours, True)
使用轮廓长度滤波筛选出符合要求的三个轮廓代码如下:
def delet_contours(contours, delete_list):
delta = 0
for i in range(len(delete_list)):
del contours[delete_list[i] - delta]
delta = delta + 1
return contours
lengths = list()
for i in range(len(contours)):
length = cv2.arcLength(contours[i], True)
lengths.append(length)
print("轮廓%d 的周长: %d" % (i, length))
min_size = 20
max_size = 200
delete_list = []
for i in range(len(contours)):
if (cv2.arcLength(contours[i], True) < min_size) or (cv2.arcLength(contours[i], True) > max_size):
delete_list.append(i)
contours = delet_contours(contours, delete_list)
print("find", len(contours), "contours left after length filter")
drawMyContours("contours after length filtering", image, contours, False)
分别绘制出所筛选出轮廓的最小覆盖矩形并标记出左上角坐标值的代码如下:
result = image.copy()
for i in range(len(contours)):
rect = cv2.minAreaRect(contours[i])
box = cv2.boxPoints(rect)
box = np.int0(box)
draw_rect = cv2.drawContours(image.copy(), [box], -1, (0, 0, 255), 2)
pt = (box[1][0],box[1][1])
cv2.circle(result, pt, 2, (0, 0, 255), 2)
text = "(" + str(pt[0]) + ", " + str(pt[1]) + ")"
cv2.putText(result, text, (pt[0] + 10, pt[1] + 10), cv2.FONT_HERSHEY_PLAIN, 1.5, (255, 255, 255), 1, 8, 0)
print("box_{}:{},左上角坐标为{}\n".format(i, box, box[1]))
image = draw_rect
cv2.imshow("draw_rect", draw_rect)
cv2.imshow("only_res", result)
将所筛选轮廓的最小覆盖矩形以及左上角坐标值绘制在同一张图片中的代码如下:
for i in range(len(contours)):
rect = cv2.minAreaRect(contours[i])
box = cv2.boxPoints(rect)
box = np.int0(box)
draw_rect = cv2.drawContours(image.copy(), [box], -1, (0, 0, 255), 2)
pt = (box[1][0], box[1][1])
circle = cv2.circle(draw_rect.copy(), pt, 2, (0, 255, 0), 2)
text = "(" + str(pt[0]) + ", " + str(pt[1]) + ")"
all = cv2.putText(circle.copy(), text, (pt[0] + 10, pt[1] + 10), cv2.FONT_HERSHEY_PLAIN, 1.5, (255, 255, 255), 1, 8, 0)
image = all
cv2.imshow("all_res", all)
最后,不能忘记
cv2.waitKey()
cv2.destroyAllWindows()
四、资料分享 关于OpenCv轮廓操作部分的详细讲解,请参考轮廓操作 关于OpenCv不同形状的轮廓拟合,请参考轮廓形状拟合 以及RGB配色表 后续会不断进行改进,希望能与大家共同进步!
|