项目记录一:用Python识别图片中指定颜色标记块并绘制其最小矩形框以及坐标点

记录准研一小白第一次动手实践课题组师姐安排的任务,非常感谢CSDN前辈们所撰写的博客对我的帮助。
一、项目背景

如图所示,有这样一张现场勘测的图片,要实现绘制出图中三个黄色标记块的最小矩形框以及左上角的坐标点
项目记录一:用Python识别图片中指定颜色标记块并绘制其最小矩形框以及坐标点_第1张图片

二、研究思路
读取图片——>提取图中黄色部分——>腐蚀操作剔除细小轮廓——>查找所有轮廓——>筛选并绘制出符合条件的轮廓——>绘制最小矩形框并标记出坐标
三、代码实现
读取图片代码如下:

# 1.读取图片
# 使用函数cv2.imread(filepath,flags)读入一副图片
image = cv2.imread(img_path)
print(image.shape)
# (5792,4344,3)
# 源图像:3通道图像
height, width, channel = image.shape
# 通过resize()函数进行图像缩放
# 缩小图像,比例为(0.125,0.125)
# 插值方法:基于4x4像素邻域的3次插值法
image = cv2.resize(image, (int(0.125*width), int(0.125*height)), interpolation=cv2.INTER_CUBIC)
# 使用函数cv2.imshow(wname,img)显示图像,第一个参数是显示图像的窗口的名字,第二个参数是要显示的图像(imread读入的图像)
cv2.imshow("original", image)

项目记录一:用Python识别图片中指定颜色标记块并绘制其最小矩形框以及坐标点_第2张图片
提取图片黄色区域代码如下:

# 2.提取图片中的黄色部分
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的参考表,获取所需要提取颜色的相应范围
项目记录一:用Python识别图片中指定颜色标记块并绘制其最小矩形框以及坐标点_第3张图片

项目记录一:用Python识别图片中指定颜色标记块并绘制其最小矩形框以及坐标点_第4张图片
通过腐蚀操作剔除一系列细小轮廓代码如下:

#腐蚀,消除图像边缘小的部分,并将图像缩小,从而使其补集扩大,原型为:dst=cv2.erode(src表示原图像,kernel表示卷积核,iterations表示迭代次数)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))  #设置kernel卷积核为 3 * 3 正方形,8位uchar型,全1结构元素
mask = cv2.erode(mask, kernel,15)
cv2.imshow("morphology", mask)

可以发现经过此操作后得到的图像明显干净了很多
项目记录一:用Python识别图片中指定颜色标记块并绘制其最小矩形框以及坐标点_第5张图片
查找所有轮廓的代码如下:

# 4.查找轮廓,输出找到的轮廓个数为5个
contours, hierarchy = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
print("find", len(contours), "contours")

# 绘制轮廓函数
# 自定义绘制轮廓的函数(为简化操作)
# 输入1:winName:窗口名
# 输入2:image:原图
# 输入3:contours:轮廓
# 输入4:draw_on_blank:绘制方式,True在白底上绘制,False:在原图image上绘制
def drawMyContours(winName, image, contours, draw_on_blank):
    # cv2.drawContours(image, contours, index, color, line_width)
    # 输入参数:
    # image:与原始图像大小相同的画布图像(也可以为原始图像)
    # contours:轮廓(python列表)
    # index:轮廓的索引(当设置为-1时,绘制所有轮廓)
    # color:线条颜色,
    # line_width:线条粗细
    # 返回绘制了轮廓的图像image
    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)

# 5.绘制原始轮廓
drawMyContours("find contours", image, contours, True)

项目记录一:用Python识别图片中指定颜色标记块并绘制其最小矩形框以及坐标点_第6张图片
使用轮廓长度滤波筛选出符合要求的三个轮廓代码如下:

#  自定义函数:用于删除列表指定序号的轮廓
#  输入 1:contours:原始轮廓
#  输入 2:delete_list:待删除轮廓序号列表
#  返回值:contours:筛选后轮廓
def delet_contours(contours, delete_list):
    delta = 0
    for i in range(len(delete_list)):
        # print("i= ", i)
        del contours[delete_list[i] - delta]
        delta = delta + 1
    return contours

# 6.筛选轮廓,计算每个轮廓长度
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)

项目记录一:用Python识别图片中指定颜色标记块并绘制其最小矩形框以及坐标点_第7张图片
分别绘制出所筛选出轮廓的最小覆盖矩形并标记出左上角坐标值的代码如下:

# 7.形状描述子
# 7.1 最小覆盖矩形
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)

项目记录一:用Python识别图片中指定颜色标记块并绘制其最小矩形框以及坐标点_第8张图片项目记录一:用Python识别图片中指定颜色标记块并绘制其最小矩形框以及坐标点_第9张图片
将所筛选轮廓的最小覆盖矩形以及左上角坐标值绘制在同一张图片中的代码如下:

# 8.标记左上角坐标点(轮廓和点在同一张图中显示)
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)

项目记录一:用Python识别图片中指定颜色标记块并绘制其最小矩形框以及坐标点_第10张图片
最后,不能忘记

#防止窗口闪现
cv2.waitKey()
#销毁所有窗口
cv2.destroyAllWindows()

四、资料分享
关于OpenCv轮廓操作部分的详细讲解,请参考轮廓操作
关于OpenCv不同形状的轮廓拟合,请参考轮廓形状拟合
以及RGB配色表
后续会不断进行改进,希望能与大家共同进步!

你可能感兴趣的