滑鼠選取區域自動馬賽克
這篇教學會延伸「偵測滑鼠事件」和「影像的馬賽克效果」兩篇文章,實作用滑鼠在影像中拖拉出一個四邊形外框,放開滑鼠後,四邊形區域就會自動加上馬賽克效果。
因為程式中的 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()
意見回饋
如果有任何建議或問題,可傳送「意見表單」給我,謝謝~