一、实验目的
用OpenCV编写一个程序,对给定图像中的局部区域打上马赛克效果,通过该实验让学生了解给图像打马赛克的原理,掌握具体的编程方法。
二、实验要求
1、用OpenCV编写一个程序,对给定图像中的局部区域打上马赛克效果,要求能通过拖动鼠标的方式让使用者灵活自主地给图像打马赛克。
2、认真撰写实验报告,要求说明实验原理,对实验过程叙述清楚,关键代码给出注释,对实验结果给出合理解释,实验分析部分则需要指出实验结果优劣的原因以及如何进一步提高实验性能的方法或手段。
3、利用python版的OpenCV编写代码。
4、每位同学独立撰写实验报告,不得相互抄袭。
三、实验过程
from cv2 import cv2 #导入openCV库
import numpy as np #导入numpy库
img=cv2.imread(r'.\CV-Pictures\015.jpg') #读取图片,采用相对路径
enable=False
def call_back_draw(event,x,y,flags,param):
global enable #定义全局变量,改正enable
if event==cv2.EVENT_LBUTTONDOWN: #鼠标左键按下
enable=True
elif event==cv2.EVENT_MOUSEMOVE and flags==cv2.EVENT_FLAG_LBUTTON: #鼠标移动,鼠标左键
if enable:
drawMask(y,x)
elif event==cv2.EVENT_LBUTTONUP: #鼠标左键抬起
enable=False
# 图像局部采样函数
def drawMask(x,y,size=10):
m=np.uint8(x/size)*size
n=np.uint8(y/size)*size
# size大小范围内的图像像素值设置为同一个像素值
for i in range(size):
for j in range(size):
img[m+i][n+j]=img[m][n]
cv2.namedWindow('image') #给窗口命名,这样可以*调节窗口的大小
cv2.setMouseCallback('image',call_back_draw) #鼠标回调函数
while True:
cv2.imshow('image',img) #图像不停的显示。
if cv2.waitKey(1)==ord('q'): #按q键退出程序
break
cv2.destroyAllWindows()
四、实验结果
实验结果如图所示,点击鼠标左键不松,实现动态给图片打马赛克,按q键退出。
五、实验分析
1.正如实验结果所示,通过循环不停的显示图像,以及openCV不停的调用鼠标回调函数,实时显示打马赛克的显示。对图片打码的本质是将将鼠标选中的部分size大小的区域设为同一个像素值,实现打码操作。但是代码的不足之处在于需要事先调好马赛克块的大小,不是很方便。可以设计一个滑动模块动态调节马赛克大小。
2.上面代码中call_back_draw函数采用openCV内置的鼠标键状态采集方法来采集鼠标位置与状态,从而可以动态的采集用户使用鼠标的状态。从而可以实时对图片打马赛克,这也是与静态打码的区别。最后输入’q’值,结束操作循环。
六、改进版代码
该代码改进了马赛克大小静态的问题,设置滑动块动态调节打马赛克的大小。可以允许在一张图像上用不同大小的马赛克对图像打码。
from cv2 import cv2
import numpy as np
img=cv2.imread(r'.\CV-Pictures\011.jpg')
enable=False
value = 10
def call_back_size(param):
global value
value = cv2.getTrackbarPos('size','image') #从滑块处获取值
def call_back_draw(event,x,y,flags,param):
global enable
global value
if event==cv2.EVENT_LBUTTONDOWN:
enable=True
elif event==cv2.EVENT_MOUSEMOVE and flags==cv2.EVENT_FLAG_LBUTTON:
if enable:
drawMask(y,x,value)
elif event==cv2.EVENT_LBUTTONUP:
enable=False
# 图像局部采样函数
def drawMask(x,y,size):
m=np.uint8(x/size)*size
n=np.uint8(y/size)*size
# size大小范围内的图像像素值设置为同一个像素值
for i in range(size):
for j in range(size):
img[m+i][n+j]=img[m][n]
cv2.namedWindow('image')
cv2.createTrackbar("size","image",value,100,call_back_size) #创建移动滑块,最大值为100
cv2.setMouseCallback('image',call_back_draw)
while True:
cv2.imshow('image',img)
if cv2.waitKey(1)==ord('q'):
break
cv2.destroyAllWindows()
实验结果:
如图所示,对鸟的眼睛,采用马赛克大小为10打码,对鸟的翅膀,采用马赛克大小为26打码。
八、代码文件
具体图片和源代码放在git方便读者使用https://gitee.com/xuhuayang/csdn/tree/master