python-Opencv选定roi,进行图片合成

发布于:2022-11-09 ⋅ 阅读:(455) ⋅ 点赞:(0)

为了实现标题中的功能,主要的代码参照了一下两篇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库我还是第一次见,孤陋寡闻了,具体作用也不了解。

做一个简单的记录。

本文含有隐藏内容,请 开通VIP 后查看