网上Opencv实现此功能的资源较多,但是想用python实现却没有相关资源,所以自己参考其他C++程序实现了这个功能。但中间还有一些问题需要改进,由于时间问题,只是简单实现了这个功能,其中还有可改进的地方,欢迎留言讨论改进。
完整代码放在附件中,需要请自取。
本文所用CV2模块版本为opencv-python== 4.5.2.52
主流程:
path = 'example.jpg'
img = cv2.imread(path)
cv2.namedWindow("")
cv2.setMouseCallback("",on_mouse,0)
cv2.imshow("",img)
if event == cv2.EVENT_LBUTTONDOWN:
Start_point = [x,y] #获取起始点,并保存
points.append(Start_point)
cv2.circle(img,tuple(Start_point),1,(255,255,255),0)
cv2.imshow("",img)
elif event == cv2.EVENT_MOUSEMOVE and flags == cv2.EVENT_FLAG_LBUTTON:
Cur_point = [x,y]
# print(points)
cv2.line(img,tuple(points[-1]),tuple(Cur_point),(255,255,255)) #以上一个点和当前点为起始和结束点,绘制轨迹
cv2.imshow("",img)
points.append(Cur_point)
elif event == cv2.EVENT_LBUTTONUP:
Cur_point=Start_point
cv2.line(img,tuple(points[-1]),tuple(Cur_point),(255,255,255))
cv2.circle(img,tuple(Cur_point),1,(255,255,255))
cv2.floodFill(img,mask_img,(x,y),(255,255,255),cv2.FLOODFILL_FIXED_RANGE)
cimg = np.zeros_like(img)
cimg[:, :, :] = 255
cv2.drawContours(cimg, contours, 1, color=(0, 0, 0), thickness=-1)
cv2.imshow('mask', cimg) # 将零件区域像素值设为(0, 0, 0)
cv2.waitKey(0)
final = cv2.bitwise_or(copyImg, cimg)
第一行中左边位原始图像,右为鼠标绘制的任意区域
第二行中左边为模板图像,右为依据模板得到的绘制区域的截图
import cv2
import os
import numpy as np
import copy
points = []
def on_mouse(event,x,y,flags,param):
global points, img,Cur_point,Start_point
copyImg = copy.deepcopy(img)
h,w = img.shape[:2]
mask_img = np.zeros([h+2,w+2],dtype=np.uint8)
if event == cv2.EVENT_LBUTTONDOWN:
Start_point = [x,y]
points.append(Start_point)
cv2.circle(img,tuple(Start_point),1,(255,255,255),0)
cv2.imshow("",img)
elif event == cv2.EVENT_MOUSEMOVE and flags == cv2.EVENT_FLAG_LBUTTON:
Cur_point = [x,y]
# print(points)
cv2.line(img,tuple(points[-1]),tuple(Cur_point),(255,255,255))
cv2.imshow("",img)
points.append(Cur_point)
elif event == cv2.EVENT_LBUTTONUP:
Cur_point=Start_point
cv2.line(img,tuple(points[-1]),tuple(Cur_point),(255,255,255))
cv2.circle(img,tuple(Cur_point),1,(255,255,255))
ret, image, mask, rect = cv2.floodFill(img,mask_img,(x,y),(255,255,255),cv2.FLOODFILL_FIXED_RANGE)
cv2.imwrite("maskImage.jpg",img)
print(np.shape(image))
segImg = np.zeros((h,w,3),np.uint8)
src =cv2.bitwise_and(img,image)
cv2.imwrite("segImg.jpg",src)
cv2.waitKey(0)
img = cv2.imread('segImg.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY_INV) # opencv里面画轮廓是根据白色像素来画的,所以反转一下。
ret, binary = cv2.threshold(gray, 240, 255, cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
contours.sort(key=lambda c: cv2.contourArea(c), reverse=True)
cv2.drawContours(copyImg, contours, -1, (0, 0, 255), 3)
cv2.imshow('RoiImg', copyImg) # 只显示零件外轮廓
cv2.waitKey(0)
cimg = np.zeros_like(img)
cimg[:, :, :] = 255
cv2.drawContours(cimg, contours, 1, color=(0, 0, 0), thickness=-1)
cv2.imshow('maskImg', cimg) # 将零件区域像素值设为(0, 0, 0)
cv2.waitKey(0)
final = cv2.bitwise_or(copyImg, cimg)
cv2.imshow('finalImg', final) # 执行或操作后生成想要的图片
cv2.waitKey(0)
if __name__ == "__main__":
path = 'example.jpg'
img = cv2.imread(path)
cv2.namedWindow("")
cv2.setMouseCallback("",on_mouse,0)
cv2.imshow("",img)
cv2.waitKey(0)
cv2.destroyAllWindows()