为了实现标题中的功能,主要的代码参照了一下两篇C站的文章,链接附上,感谢作者的分享。
我调用了一下,侵删。
python+opencv代码给证件照换底色_木心心以向荣的博客-CSDN博客
OpenCV-Python选择ROI(矩形和多边形)_木头VS星星的博客-CSDN博客OpenCV-Python选择ROI(矩形和多边形)_木头VS星星的博客-CSDN博客OpenCV-Python选择ROI(矩形和多边形)_木头VS星星的博客-CSDN博客
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库我还是第一次见,孤陋寡闻了,具体作用也不了解。
做一个简单的记录。