Python OpenCV图像采样与马赛克处理详解
本文详细解析Python中使用OpenCV进行图像采样的原理与实现。通过调整采样间隔,探讨其对图像空间分辨率及数据量的影响,并提供灰度图与彩色图的整图采样代码。此外,文章还介绍了如何处理图像边缘未整除的情况,并实现了基于鼠标交互的局部区域马赛克采样功能,帮助读者掌握基础图像处理技术。
一.图像采样处理原理
图像采样(Image Sampling)是指在空间维度上对连续图像进行离散化分割,将其划分为M×N个网格单元。每个网格单元通过一个亮度值或灰度值来代表该区域的图像信息,具体示意可参考图9-1。

采样间隔的大小直接决定了图像的质量与数据量。当采样间隔增大时,生成的图像像素数量减少,导致空间分辨率降低,图像质量下降,严重时会出现明显的马赛克效应;反之,采样间隔缩小则能增加像素数量,提升空间分辨率和图像质量,但会显著增加数据存储空间。图9-2对比了不同采样间隔下的“Lena”图像效果:图(a)为原始图像,图(b)为128×128采样,图(c)为64×64采样,图(d)为32×32采样,图(e)为16×16采样,图(f)为8×8采样[1-3]。

二.图像采样实现
在Python中实现图像采样的核心流程如下:首先创建一张与原图尺寸相同的临时图像,设定采样的网格大小(例如16×16)。接着,遍历原始图像的所有像素点,根据网格划分,将每个采样区域内的像素值统一赋为该区域左上角像素的灰度值或颜色值,从而完成图像采样处理。
# -*- coding: utf-8 -*-
# By:Eastmount
import cv2
import numpy as np
import matplotlib.pyplot as plt
#读取原始图像
img = cv2.imread('lena-hd.png')
#获取图像高度和宽度
height = img.shape[0]
width = img.shape[1]
#采样转换成16*16区域
numHeight = int(height/16)
numWidth = int(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("Sampling", new_img)
#等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()
上述代码的运行结果如图9-3所示,展示了将灰度图像按16×16区域进行采样的效果。

同样的逻辑适用于彩色图像。以下代码演示了将“小珞珞”图像采样为8×8马赛克区域的处理过程。
# -*- coding: utf-8 -*-
# By:Eastmount
import cv2
import numpy as np
import matplotlib.pyplot as plt
#读取原始图像
img = cv2.imread('luo.png')
#获取图像高度和宽度
height = img.shape[0]
width = img.shape[1]
#采样转换成8×8区域
numHeight = int(height/8)
numwidth = int(width/8)
#创建一幅图像
new_img = np.zeros((height, width, 3), np.uint8)
#图像循环采样8*8区域
for i in range(8):
#获取Y坐标
y = i*numHeight
for j in range(8):
#获取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("Sampling", new_img)
#等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()
运行结果如图9-4所示,彩色图像被成功采样为8×8的区域块。

需要注意的是,上述基础代码在图像长宽无法被采样区域尺寸整除时,会导致图像右侧和下侧边缘区域未被处理。建议通过求余运算,对这部分剩余区域进行相应的采样填充,以确保图像完整性。
三.图像局部采样处理
前述示例针对整幅图像进行采样。若需对图像的特定局部区域进行马赛克处理,可通过引入鼠标交互事件来实现。以下代码实现了当鼠标按下并拖动时,对拖动区域实时打上马赛克,并按下“s”键将处理后的图像保存至本地的功能。
# -*- coding: utf-8 -*-
# By:Eastmount
import cv2
import numpy as np
import matplotlib.pyplot as plt
#读取原始图像
im = cv2.imread('luo.png', 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 = int(x / size * size)
n = int(y / size * size)
print(m, n)
#10*10区域设置为同一像素值
for i in range(size):
for j in range(size):
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()
如图9-5所示,该功能成功对人物面部区域进行了马赛克处理。

四.总结
本文系统讲解了图像采样的基本概念、整图与局部采样的Python实现方法,并补充了局部马赛克处理的交互案例。掌握这些知识点有助于将现实图像转换为数字形式,为后续更复杂的图像处理任务奠定基础。
以上就是Python图片处理之图片采样处理详解的详细内容,更多关于Python图片采样处理的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









