天天看点

绘制简单封闭图形并且进行填充

思路:绘制封闭曲线,获得轮廓, 对轮廓进行填充      
因为在绘制曲线的时候,记录了起始点和最后一个点的坐标,用以使曲线封闭,所以绘制的时候只需要绘制到起点的附近区域即可,松开鼠标后,曲线连接起点和终点,实现封闭      

注意:该代码不适合绘制复杂图形

import numpy as np
import matplotlib.pyplot as plt
from numpy.core.defchararray import count
import cv2 as cv


#step 1. 读取,预处理
img_source = cv.imread("duo.jpg")  #原图(三通道)
img = cv.cvtColor(img_source, cv.COLOR_BGR2GRAY)  #转为灰度图像(单通道),便于查找轮廓
img[:,:] = 0  #改成黑色图像,用于获取所绘制的闭合曲线的轮廓
cv.namedWindow('image', cv.WINDOW_AUTOSIZE)  #在原图中显示
cv.namedWindow('test')

#step 2. 绘制任意形状的图形
drawing = False  #开始鼠标移动绘图模式
ix, iy= -1, -1
px, py = -1, -1
#call back function
def drawCurve(event, x, y, flags, param):
    global ix, iy, drawing, px, py
    if event == cv.EVENT_LBUTTONDOWN:
        drawing = True
        print("start point")
        ix, iy = x, y
        px, py = x, y
    elif event == cv.EVENT_MOUSEMOVE:
        if drawing:  #关键是如何记录相邻两次的坐标
            print("mouse move")
            #用于获得轮廓的图像
            cv.circle(img, (x, y), 1, (255, 255, 255), -1)   #注意灰度图像中的白色是全部255
            cv.line(img, (ix, iy), (x,y), (255, 255, 255), 2)  #关键是如何记录相邻两次的坐标
            #在原图中显示
            cv.circle(img_source, (x, y), 1, (0, 255, 255), -1)
            cv.line(img_source, (ix, iy), (x,y), (0, 255, 255), 2)
            ix, iy = x,y              #用来记录上一个点的坐标
    elif event == cv.EVENT_LBUTTONUP:
        drawing = False
        #使曲线闭合, 用于获取轮廓
        cv.line(img, (x, y), (px, py), (255, 255, 255), 2)  #将曲线补充成闭合曲线
        #仅用于在原图中显示
        cv.line(img_source, (x, y), (px, py), (0, 255, 255), 2)  #将曲线补充成闭合曲线

cv.setMouseCallback("image", drawCurve)  #可以在原图中直接绘制
cv.setMouseCallback('test', drawCurve)  #可以在获得轮廓的图中直接绘制
while True:
    k = cv.waitKey(1)
    cv.imshow("image", img_source)  #显示原图
    cv.imshow("test", img)   #显示获取轮廓的图像
    if k == 27:
        break


#step 3. 查找轮廓
#一般情形考虑先二值化,因为这里获取轮廓的图像在前两部的操作过程中只有黑白两种颜色(轮廓为白)
contours, hierarchy = cv.findContours(img, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
cv.drawContours(img_source, contours, -1, (0,255,0), -1)
print("congralations!")


#step 4. 给轮廓填充颜色
cv.fillPoly(img_source,[contours[1]],(255,0,0))  #填充内部
cv.imshow("result", img_source)


cv.waitKey(0)
cv.destroyAllWindows()

print('hello world')
           

 测试图像:

绘制简单封闭图形并且进行填充
因为在绘制曲线的时候,记录了起始点和最后一个点的坐标,用以使曲线封闭,所以绘制的时候只需要绘制到起点的附近区域即可,松开鼠标后,曲线连接起点和终点,实现封闭