- 图像马赛克功能实现
- UI界面实现
一、图像采样原理
图像采样(Image Sampling)处理是讲一幅连续图像在空间上分割成MxN个网格,每个网格用一个亮度值或灰度值来表示,其示意图如下。
图像采样的间隔越大,所得图像像素数越少,空间分辨率越低,图像质量越差,甚至出现马赛克效应;相反,图像采样的间隔越小,所得图像像素数越多,空间分辨率越高,图像质量越好,但数据量会相应的增大。下图为不同采样间隔的“lena”图。
二、Python图像采样处理
首先建立一张临时图片,设置需要采样的区域大小(如16x16),接着循环变力原始图像中所有像素点,采样区域内的像素点赋值相同(如左上角像素点的灰度值),最终实现图像采样处理。以下代码为16x16采样过程。
# -*- coding: utf-8 -*-
import cv2
import numpy as np
import matplotlib.pyplot as plt
#读取原始图像
img = cv2.imread('lena.png')
#获取图像高度和宽度
height = img.shape[0]
width = img.shape[1]
#采样转换成16*16区域
numHeight = height/16
numwidth = width/16
#创建一幅图像
new_img = np.zeros((height, width, 3), np.uint8)
#图像循环采样16*16区域
for i in range(16):
#获取Y坐标
y = i*numHeight
for j in range(16):
#获取X坐标
x = j*numwidth
#获取填充颜色 左上角像素点
b = img[y, x][0]
g = img[y, x][1]
r = img[y, x][2]
#循环设置小区域采样
for n in range(numHeight):
for m in range(numwidth):
new_img[y+n, x+m][0] = np.uint8(b)
new_img[y+n, x+m][1] = np.uint8(g)
new_img[y+n, x+m][2] = np.uint8(r)
#显示图像
cv2.imshow("src", img)
cv2.imshow("", new_img)
#等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()
三、局部马赛克处理
当鼠标按下时,读取鼠标的坐标像素位置,给鼠标拖动的区域打上马赛克。
# -- coding:utf-8 --
import cv2
import numpy as np
import matplotlib.pyplot as plt
def mosaic_function(instance):
# 读取原始图像
imgfile = instance.root_path+'/part4/images_mos/test.png'
imgfile = instance.mosaic_original[0][0]
print(instance.mosaic_original[0][0])
im = cv2.imread(imgfile, 1)
# 设置鼠标左键开启
en = False
# 鼠标事件
def draw(event, x, y, flags, param):
global en
# 鼠标左键按下开启en值
if event == cv2.EVENT_LBUTTONDOWN:
en = True
# 鼠标左键按下并且移动
elif event == cv2.EVENT_MOUSEMOVE and flags == cv2.EVENT_LBUTTONDOWN:
# 调用函数打马赛克
if en:
drawMask(y, x)
# 鼠标左键弹起结束操作
elif event == cv2.EVENT_LBUTTONUP:
en = False
# 图像局部采样操作
def drawMask(x, y, size=10):
# size*size采样处理
m = x / size * size
n = y / size * size
m=int(m)
n=int(n)
print(m,n)
# 10*10区域设置为同一像素值
for i in range(size):
for j in range(size):
print (j)
im[m + i][n + j] = im[m][n]
# 打开对话框
cv2.namedWindow('image')
# 调用draw函数设置鼠标操作
cv2.setMouseCallback('image', draw)
# 循环处理
while (1):
cv2.imshow('image', im)
# 按ESC键退出
if cv2.waitKey(10) & 0xFF == 27:
break
# 按s键保存图片
elif cv2.waitKey(10) & 0xFF == 115:
cv2.imwrite('sava.png', im)
# 退出窗口
cv2.destroyAllWindows()
#设置画笔大小
UI编写:
""""""""""""" 马赛克 """""""""""""
# 创建一个窗口,定义位置,标题等属性
instance.widget_mosaic = QWidget()
instance.widget_mosaic.setGeometry(200, 200, 500, 200)
instance.widget_mosaic.setWindowTitle('马赛克')
# 创建一个按钮,该按钮的父对象为instance.widget_mosaic
# 当该按钮被点击时执行信号发射函数
instance.button_widget_mosaic = QPushButton("执行", instance.widget_mosaic)
instance.button_widget_mosaic.setGeometry(30, 30, 50, 50)
instance.button_widget_mosaic.clicked.connect(instance.signal_mosaic_emit)
# 创建一个action,当该action被触发时运行show_mosaic
action_mosaic_widget_show = QAction('&图像马赛克', instance)
action_mosaic_widget_show.triggered.connect(instance.show_mosaic_widget)
# 原图图片路径——马赛克
instance.mos_img=""
instance_button_choose_original_image=QPushButton("选择原图",instance.widget_mosaic)
instance_button_choose_original_image.clicked.connect(instance.open_file_and_change_name_mos)
# 用于显示路径名的label
instance.label_mosaic_original = QLabel(instance.widget_mosaic)
instance.label_mosaic_original.setGeometry(30,120,500,50)
instance.label_mosaic_original.setText("文件路径")
# 用于显示功能操作的label
instance.label_mosaic_tip_original = QLabel(instance.widget_mosaic)
instance.label_mosaic_tip_original.setGeometry(30,70,500,50)
instance.label_mosaic_tip_original.setText("按ESC退出 按S键保存处理后的图片")
运行成果: