为了实现标题中的功能,主要的代码参照了一下两篇C站的文章,链接附上,感谢作者的分享。
我调用了一下,侵删。
python+opencv代码给证件照换底色_木心心以向荣的博客-CSDN博客
OpenCV-Python选择ROI(矩形和多边形)_木头VS星OpenCV-Python选择ROI(矩形和多边形)_木头VS星星的博客-CSDN博客OpenCV-Python选择ROI(矩形和多边形)_木头VS星
python黑色变白色_在OpenCV python中将白色像素转换为黑色_weixin_39862716的博客-CSDN博客
第一个作者的分享可谓是帮了我的大忙,很有用的讲解。
第二个作者的ROI选择可以说是关键了,没有就无从实现了。
第三个作者的文章帮助实现了一个关键的功能。
其实我所做的都是CV活,因为暂时想不到更好的虚化方式,也请评论区大佬不吝赐教,如何可以像相机一样虚化的更真实一些,图片还是有很强的颗粒感。
话不多说,代码怼上
import cv2 import imutils import numpy as np import joblib def get_num(): n = int(input('请输入想要进行模糊计算的次数')) t = int(input('请输入卷积的边长')) t =2*t+1 return (n,t) pts = [] # 用于存放点 # 统一的:mouse callback function def draw_roi(event, x, y, flags, param): img2 = img.copy() rows, cols, channels = img.shape if event == cv2.EVENT_LBUTTONDOWN: # 左键点击,选择点 pts.append((x, y)) if event == cv2.EVENT_RBUTTONDOWN: # 右键点击,取消最近一次选择的点 pts.pop() if event == cv2.EVENT_MBUTTONDOWN: # 中键绘制轮廓 mask = np.zeros(img.shape, np.uint8) points = np.array(pts, np.int32) points = points.reshape((-1, 1, 2)) # 画多边形 mask = cv2.polylines(mask, [points], True, (255, 255, 255), 2) mask2 = cv2.fillPoly(mask.copy(), [points], (255, 255, 255)) # 用于求 ROI mask3 = cv2.fillPoly(mask.copy(), [points], (0, 255, 0)) # 用于 显示在桌面的图像 show_image = cv2.addWeighted(src1=img, alpha=0.8, src2=mask3, beta=0.2, gamma=0) cv2.imshow("mask", mask2) # cv2.imshow("show_img", show_image) ROI = cv2.bitwise_and(mask2, img) n, t = get_num() for i in range(int(n)): ROI = cv2.blur(ROI,(int(t),int(t))) cv2.imshow("ROI", ROI) lower = np.array([0,0,0]) upper = np.array([155,155,155]) mask4 = cv2.inRange(mask2, lower, upper) erode = cv2.erode(mask4, None, iterations=1) dilate = cv2.dilate(erode, None, iterations=1) gray = cv2.cvtColor(mask2, cv2.COLOR_BGR2GRAY) ret, thresh = cv2.threshold(gray, 240, 255, cv2.THRESH_BINARY) white_px = np.asarray([255, 255, 255]) black_px = np.asarray([0, 0, 0]) (row, col) = thresh.shape img_array = np.array(mask2) for r in range(row): for c in range(col): px = thresh[r][c] if all(px == white_px): img_array[r][c] = black_px kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (int(t), int(t))) mask5 = cv2.erode(img_array, kernel, iterations=1) for i in range(rows): for j in range(cols): if dilate[i, j] == 255: mask5[i, j] = img2[i, j] cv2.imshow("mask5",mask5) dst = cv2.bitwise_or(ROI,mask5) cv2.imshow("new_img",dst) cv2.waitKey(0) if len(pts) > 0: # 将pts中的最后一点画出来 cv2.circle(img2, pts[-1], 3, (0, 0, 255), -1) if len(pts) > 1: # 画线 for i in range(len(pts) - 1): cv2.circle(img2, pts[i], 5, (0, 0, 255), -1) # x ,y 为鼠标点击地方的坐标 cv2.line(img=img2, pt1=pts[i], pt2=pts[i + 1], color=(255, 0, 0), thickness=2) cv2.imshow('image', img2) # 创建图像与窗口并将窗口与回调函数绑定 img = cv2.imread("D:\spypy\py/bs2/timg.jpg") img = imutils.resize(img, width=500) cv2.namedWindow('image') cv2.setMouseCallback('image', draw_roi) print("[INFO] 单击左键:选择点,单击右键:删除上一次选择的点,单击中键:确定ROI区域") print("[INFO] 按‘S’确定选择区域并保存") print("[INFO] 按 ESC 退出") while True: key = cv2.waitKey(1) & 0xFF if key == 27: break if key == ord("s"): saved_data = { "ROI": pts } joblib.dump(value=saved_data, filename="config.pkl") print("[INFO] ROI坐标已保存到本地.") break cv2.destroyAllWindows()
有错误请指正,imutil库和joblib库我还是第一次见,孤陋寡闻了,具体作用也不了解。
做一个简单的记录。