鼠标选取自动马赛克
这篇教学会延伸“侦测鼠标事件”和“图像的马赛克效果”两篇文章,实作用鼠标在图像中拖拉出一个四边形外框,放开鼠标后,四边形区域就会自动加上马赛克效果。
因为程序中的 OpenCV 会需要使用镜头或 GPU,所以请使用本机环境 ( 参考:使用 Python 虚拟环境 ) 或使用 Anaconda Jupyter 进行实作 ( 参考:使用 Anaconda ) ,并安装 OpenCV 函数库 ( 参考:OpenCV 函数库 )。
用鼠标在图像中拖拉出四边形
下方的程序执行后,会先建立两个空串列记录两组座标 ( 绘制四边形需要两个对角端点座标 ),接着使用 flag 判断在鼠标拖曳事件发生时,不断更新座标位置 ( 第一个座标不更动,不断更新第二个座标点 ),就能在图像中绘制出四边形。
import cv2
img = cv2.imread('mona.jpg')
dot1 = [] # 記錄第一個座標
dot2 = [] # 記錄第二個座標
# 滑鼠事件發生時要執行的函式
def show_xy(event,x,y,flags,param):
global dot1, dot2, img # 在函式內使用全域變數
# 滑鼠拖曳發生時
if flags == 1:
if event == 1:
dot1 = [x, y] # 按下滑鼠時記錄第一個座標
if event == 0:
img2 = img.copy() # 拖曳時不斷複製 img
dot2 = [x, y] # 拖曳時不斷更新第二個座標
# 根據兩個座標繪製四邊形
cv2.rectangle(img2, (dot1[0], dot1[1]), (dot2[0], dot2[1]), (0,0,255), 2)
# 不斷顯示新圖片 ( 如果不這麼做,會出現一堆四邊形殘影 )
cv2.imshow('oxxostudio', img2)
cv2.imshow('oxxostudio', img)
cv2.setMouseCallback('oxxostudio', show_xy)
cv2.waitKey(0) # 按下任意鍵結束
cv2.destroyAllWindows()
将程序稍做修改,加上判断“鼠标放开”的事件,就能保留拖曳出的四边形区域。
import cv2
img = cv2.imread('mona.jpg')
dot1 = []
dot2 = []
def show_xy(event,x,y,flags,param):
global dot1, dot2, img, img2 # 因為要讓 img = img2,所以也要宣告 img2 為全域變數
if flags == 1:
if event == 1:
dot1 = [x, y]
if event == 0:
img2 = img.copy()
dot2 = [x, y]
cv2.rectangle(img2, (dot1[0], dot1[1]), (dot2[0], dot2[1]), (0,0,255), 2)
cv2.imshow('oxxostudio', img2)
if event == 4:
img = img2 # 滑鼠放開時 ( event == 4 ),將 img 更新為 img2
cv2.imshow('oxxostudio', img)
cv2.setMouseCallback('oxxostudio', show_xy)
cv2.waitKey(0)
cv2.destroyAllWindows()
将鼠标选取区域自动马赛克
将上方的程序码里,加入“图像的马赛克效果”的范例,就能在拖曳出四边形区域后,自动将该区域的图像马赛克。
import cv2
img = cv2.imread('mona.jpg')
dot1 = []
dot2 = []
def show_xy(event,x,y,flags,param):
global dot1, dot2, img, img2
if flags == 1:
if event == 1:
dot1 = [x, y]
if event == 0:
img2 = img.copy()
dot2 = [x, y]
cv2.rectangle(img2, (dot1[0], dot1[1]), (dot2[0], dot2[1]), (0,0,255), 2)
cv2.imshow('oxxostudio', img2)
if event == 4:
level = 8 # 縮小比例 ( 可當作馬賽克的等級 )
h = int((dot2[0] - dot1[0]) / level) # 按照比例縮小後的高度 ( 使用 int 去除小數點 )
w = int((dot2[1] - dot1[1]) / level) # 按照比例縮小後的寬度 ( 使用 int 去除小數點 )
mosaic = img[dot1[1]:dot2[1], dot1[0]:dot2[0]] # 取得馬賽克區域
mosaic = cv2.resize(mosaic, (w, h), interpolation=cv2.INTER_LINEAR) # 根據縮小尺寸縮小
mosaic = cv2.resize(mosaic, (dot2[0] - dot1[0], dot2[1] - dot1[1]), interpolation=cv2.INTER_NEAREST) # 放大到原本的大小
img[dot1[1]:dot2[1], dot1[0]:dot2[0]] = mosaic # 置換成馬賽克的影像
cv2.imshow('oxxostudio', img)
cv2.imshow('oxxostudio', img)
cv2.setMouseCallback('oxxostudio', show_xy)
cv2.waitKey(0)
cv2.destroyAllWindows()
微信扫码关注
抖音扫码关注