《零基础入门AI:OpenCV图像预处理进一步学习》

本文全面讲解OpenCV图像预处理的七大核心技术(插值方法、边缘填充、图像矫正(透视变换)、图像掩膜、ROI切割、图像添加水印、图像噪点消除),每个知识点都配有详细解释和实用代码示例,帮助初学者建立系统的图像处理知识体系。


一、插值方法:图像缩放的核心技术

插值是在图像缩放或旋转时估算新像素值的方法,不同方法在速度和质量上有显著差异。

1. 最近邻插值

  • 原理:直接取最邻近像素的值
  • 特点:速度最快,但会产生锯齿
  • 适用场景:实时系统或低功耗设备
resized = cv2.resize(img, (800, 600), interpolation=cv2.INTER_NEAREST)

2. 双线性插值

  • 原理:取周围4个像素的加权平均值
  • 特点:速度与质量平衡
  • 适用场景:大多数常规缩放需求
resized = cv2.resize(img, (800, 600), interpolation=cv2.INTER_LINEAR)

3. 双三次插值

  • 原理:取周围16个像素的加权平均值
  • 特点:质量高但速度慢
  • 适用场景:高质量图像处理
resized = cv2.resize(img, (800, 600), interpolation=cv2.INTER_CUBIC)

4. Lanczos插值

  • 原理:使用sinc函数进行插值
  • 特点:最高质量,最慢速度
  • 适用场景:专业图像处理
resized = cv2.resize(img, (800, 600), interpolation=cv2.INTER_LANCZOS4)

5.完整示例

import cv2

# 读图
cat = cv2.imread('../images/1.jpg')
w = cat.shape[1]
h = cat.shape[0]

# 旋转
# 获取旋转矩阵
M = cv2.getRotationMatrix2D((w//2, h//2), 45, 0.5)

# 应用仿射变换函数
dst = cv2.warpAffine(cat, M, (w, h))

# 最近邻插值  flags=cv2.INTER_NEAREST
dst1 = cv2.warpAffine(cat, M, (w, h), flags=cv2.INTER_NEAREST)

# 双线性插值  单线性插值  插两次:水平和垂直
dst2 = cv2.warpAffine(cat, M, (w, h), flags=cv2.INTER_LINEAR)

# 像素区域插值  缩小:均值滤波   放大:整数  最近邻  不是整数  双线性 4点  2 x 2
dst3 = cv2.warpAffine(cat, M, (w, h), flags=cv2.INTER_AREA)

# 双三次插值  16个  4 x 4  w_i   w_j
dst4 = cv2.warpAffine(cat, M, (w, h), flags=cv2.INTER_CUBIC)

# Lanczos插值  64个  8 x 8
dst5 = cv2.warpAffine(cat, M, (w, h), flags=cv2.INTER_LANCZOS4)

# 显示
cv2.imshow('dst', dst)
cv2.imshow('dst1', dst1)
cv2.imshow('dst2', dst2)
cv2.imshow('dst3', dst3)
cv2.imshow('dst4', dst4)
cv2.imshow('dst5', dst5)

cv2.waitKey(0)
cv2.destroyAllWindows()

二、边缘填充:处理边界问题的关键

当进行卷积操作时,图像边界需要特殊处理,OpenCV提供多种填充方式。

1. 填充方法对比

方法原理效果示例
BORDER_REPLICATE复制边界像素值`aaaa
BORDER_REFLECT镜像反射边界`fedc
BORDER_REFLECT_101反射不含边界`gfed
BORDER_CONSTANT用常数填充`0000
BORDER_WRAP循环填充`cdef

2. 完整示例

import cv2

# 读图
cat = cv2.imread('../images/1.jpg')
w = cat.shape[1]
h = cat.shape[0]

# 旋转
# 获取旋转矩阵
M = cv2.getRotationMatrix2D((w//2, h//2), 45, 0.5)

# 应用仿射变换函数
dst = cv2.warpAffine(cat, M, (w, h))

# 最近邻插值   边界复制
dst1 = cv2.warpAffine(cat, M, (w, h), flags=cv2.INTER_NEAREST,borderMode=cv2.BORDER_REPLICATE)

# 双线性插值    边界反射
dst2 = cv2.warpAffine(cat, M, (w, h), flags=cv2.INTER_LINEAR,borderMode=cv2.BORDER_REFLECT)

# 像素区域插值   边界反射101
dst3 = cv2.warpAffine(cat, M, (w, h), flags=cv2.INTER_AREA,borderMode=cv2.BORDER_REFLECT_101)

# 双三次插值  边界常数
dst4 = cv2.warpAffine(cat, M, (w, h), flags=cv2.INTER_CUBIC,borderMode=cv2.BORDER_CONSTANT,borderValue=(0,0,255))

# Lanczos插值  边界包裹
dst5 = cv2.warpAffine(cat, M, (w, h), flags=cv2.INTER_LANCZOS4,borderMode=cv2.BORDER_WRAP)

# 显示
cv2.imshow('dst', dst)
cv2.imshow('dst1', dst1)
cv2.imshow('dst2', dst2)
cv2.imshow('dst3', dst3)
cv2.imshow('dst4', dst4)
cv2.imshow('dst5', dst5)

cv2.waitKey(0)
cv2.destroyAllWindows()

三、图像矫正:透视变换的应用

透视变换可以将倾斜视角的图像矫正为正视角,常用于文档扫描和车牌识别。

1. 透视变换四步法

  1. 识别源点:选择图像中的四个特征点
  2. 定义目标点:确定矫正后的位置
  3. 计算变换矩阵:使用getPerspectiveTransform
  4. 应用变换:使用warpPerspective

2. 完整示例

import cv2
import numpy as np

# 读图
card = cv2.imread('../images/3.png')
shape = card.shape

# 获取透视变换矩阵
# 原图中卡片的四个角点:左上、右上、左下、右下
# [[178, 100], [487, 134], [124, 300], [490, 350]]
pt1 =np.float32([[178, 100], [487, 134], [124, 300], [490, 350]])
pt2 =np.float32([[0,0],[shape[1],0],[0,shape[0]],[shape[1],shape[1]]])

M = cv2.getPerspectiveTransform(pt1,pt2)

# 透视变换
dst = cv2.warpPerspective(card,M,(shape[1],shape[0]),cv2.INTER_LINEAR,borderMode=
                          cv2.BORDER_REFLECT)

cv2.imshow('card',card)
cv2.imshow('dst',dst)

cv2.waitKey(0)
cv2.destroyAllWindows()

四、图像掩膜:精确控制处理区域

掩膜是二值化图像,用于指定哪些区域需要处理或保留,以实现特定任务的目标。

掩膜操作三部曲

  1. 创建掩膜:手动绘制或通过阈值处理生成
  2. 应用掩膜:使用按位与操作保留目标区域
  3. 颜色替换:修改特定区域颜色

第一种:

# 创建圆形掩膜
mask = np.zeros(img.shape[:2], dtype=np.uint8)
cv2.circle(mask, (200, 200), 100, 255, -1)

# 应用掩膜
masked_img = cv2.bitwise_and(img, img, mask=mask)

# 颜色替换
img[mask == 255] = (0, 255, 0)  # 将掩膜区域变为绿色

第两种(完整):

cv2.inRange用于进行多通道图像(尤其是彩色图像)的阈值操作。

import cv2
import numpy as np

# 读图
demo = cv2.imread('../images/demo.png')
demo = cv2.resize(demo,(500,500))

# 颜色空间转换  转 HSV
demo_hsv = cv2.cvtColor(demo,cv2.COLOR_BGR2HSV)

# 定义颜色范围
low = np.array([0,43,46])
high = np.array([10,255,255])

# 创建掩膜  cv2.inRange(img,low,high)  传 hsv 颜色空间下的图像  二维
mask = cv2.inRange(demo_hsv,low,high)

# 颜色提取 cv2.bitwise_and(src1,src2[,mask])   传的是原图
dst = cv2.bitwise_and(demo,demo,mask=mask)

cv2.imshow('demo',demo)
cv2.imshow('mask',mask)
cv2.imshow('dst',dst)

cv2.waitKey(0)
cv2.destroyAllWindows()

含颜色替换操作示例:

import cv2
import numpy as np

# 读图
demo = cv2.imread('../images/demo.png')
demo = cv2.resize(demo,(500,500))

# 颜色空间转换  转 HSV
demo_hsv = cv2.cvtColor(demo,cv2.COLOR_BGR2HSV)

# 定义颜色范围
low = np.array([0,43,46])
high = np.array([10,255,255])

# 创建掩膜  cv2.inRange(img,low,high)  传 hsv 颜色空间下的图像  二维
mask = cv2.inRange(demo_hsv,low,high)

# 颜色替换  布尔索引
arr = (mask == 255)
# print(arr)

demo[arr] = (0, 255, 0)
# demo[mask == 255] = (0, 255, 0)

cv2.imshow('demo',demo)

cv2.waitKey(0)
cv2.destroyAllWindows()

五、ROI切割:聚焦关键区域

ROI(Region of Interest)是图像中需要特别关注的区域。

ROI操作技巧

# 直接选择矩形区域
roi = img[100:300, 200:400]  # y1:y2, x1:x2

# 在原始图像上绘制ROI框
cv2.rectangle(img, (200, 100), (400, 300), (0, 255, 0), 2)

# 处理ROI区域(例如转换为灰度)
roi_gray = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)

六、图像添加水印:版权保护技术

水印技术可分为可见水印和不可见水印。

1. 三步骤:

  • 模板输入:使用模板输入所输入的图片其实是作为要添加的水印,有了水印的彩色图之后,我们需要用它来制作一个掩模,这就用到了灰度化和二值化,即先灰度化后二值化,这就得到了带有水印图案的掩模。
  • 与运算:有了模板的掩膜后(也就是二值化图),在要添加水印的图像中,根据掩膜的大小切割出一个ROI区域,也就是要添加水印的区域,让其与模板的掩膜进行与运算。与运算的过程中,只要有黑色像素,那么得到的结果图中的对应位置也会是黑色像素。由于模板的掩膜中目标物体的像素值为黑色,所以经过与运算后,就会在ROI区域中得到模板图的形状。
  • 图像融合:将模板的形状添加到水印区域之后,就可以将该图像与原始的模板图进行图像融合。该组件的目的就是将图像对应的数组中的对应元素进行相加(一定要注意这里的两个数组是规格相同的,也就是说要么都是灰度图,要么都是彩图),其过程如下图所示。

2. 可见水印实现

# 读取水印图片
watermark = cv2.imread("watermark.png", cv2.IMREAD_UNCHANGED)

# 调整水印大小
watermark = cv2.resize(watermark, (200, 100))

# 提取alpha通道
watermark_img = watermark[:, :, :3]
alpha = watermark[:, :, 3] / 255.0

# 创建叠加区域
roi = img[10:110, 10:210]

# 混合图像
for c in range(3):
    roi[:, :, c] = (1 - alpha) * roi[:, :, c] + alpha * watermark_img[:, :, c]

3. 完整示例:

import cv2

# 读图
bg = cv2.imread('../images/bg.png')
logo = cv2.imread('../images/logohq.png')
h, w = logo.shape[0:2]   # h, w
roi = bg[0:h, 0:w]

# 转为灰度图
gray = cv2.cvtColor(logo, cv2.COLOR_BGR2GRAY)

# 二值化
# 黑 logo 白底(阈值法 小于阈值的变黑,大于阈值的设maxval/变白)   与上背景
_, mask1 = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY)
bg1 = cv2.bitwise_and(roi, roi, mask=mask1)

# 白 logo黑底(反阈值法  大于阈值变黑,小于阈值的设maxval/变白)  与上 logo
_, mask2 = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY_INV)
bg2 = cv2.bitwise_and(logo, logo, mask=mask2)

# 融合  两个结果相加
roi[:] = cv2.add(bg1,bg2)  # 直接对 roi 修改,就能实现原背景改变,因为切片出来的 roi和原背景变量指向内存同一块地址
# dst = cv2.add(bg1,bg2)
# roi[:] = dst

cv2.imshow('mask1', mask1)
cv2.imshow('bg1', bg1)
cv2.imshow('mask2', mask2)
cv2.imshow('bg2', bg2)
cv2.imshow('roi', roi)
cv2.imshow('bg', bg)

cv2.waitKey(0)
cv2.destroyAllWindows()

七、图像噪点消除:提升图像质量

噪声是图像中随机出现的像素值变化,常见滤波方法如下:

1. 均值滤波

  • 原理:取邻域内像素的平均值
  • 效果:消除高斯噪声,但模糊边缘
blur = cv2.blur(img, (5, 5))

2. 高斯滤波

  • 原理:加权平均,中心点权重最高
  • 效果:有效消除高斯噪声
gaussian = cv2.GaussianBlur(img, (5, 5), 0)

3. 中值滤波

  • 原理:取邻域内像素的中值
  • 效果:消除椒盐噪声,保留边缘
median = cv2.medianBlur(img, 5)

4. 双边滤波

  • 原理:同时考虑空间距离和像素值差异
  • 效果:保留边缘同时减少噪声
bilateral = cv2.bilateralFilter(img, 9, 75, 75)

5. 滤波器选择指南

噪声类型推荐滤波器参数示例
高斯噪声高斯滤波(5,5), σ=0
椒盐噪声中值滤波内核大小=5
边缘保护双边滤波d=9, σColor=75, σSpace=75

6. 完整示例:

import cv2

# 读图
lvbo2 = cv2.imread('../images/lvbo2.png')
lvbo3 = cv2.imread('../images/lvbo3.png')

# 均值滤波
dst1 = cv2.blur(lvbo2,(3,3))

# 方框滤波  底层使用饱和运算 最大255 及白的很多
dst2 = cv2.boxFilter(lvbo2,-1,(3,3),normalize=False)

# 高斯滤波
dst3 = cv2.GaussianBlur(lvbo2,(3,3),1)

# 中值滤波  非线性(逻辑操作)
dst4 = cv2.medianBlur(lvbo3,3)

# 双边滤波
dst5 = cv2.bilateralFilter(lvbo2,7,75,75)

cv2.imshow('lvbo2',lvbo2)
# cv2.imshow('lvbo3',lvbo3)
cv2.imshow('dst1',dst1)
# cv2.imshow('dst2',dst2)
# cv2.imshow('dst3',dst3)
# cv2.imshow('dst4',dst4)
cv2.imshow('dst5',dst5)

cv2.waitKey(0)
cv2.destroyAllWindows()

图像预处理综合应用

def advanced_preprocessing(image_path):
    # 1. 读取图像
    img = cv2.imread(image_path)
    
    # 2. 透视变换矫正
    src_pts = np.float32([[58, 72], [375, 65], [35, 392], [400, 398]])
    dst_pts = np.float32([[0, 0], [500, 0], [0, 600], [500, 600]])
    M = cv2.getPerspectiveTransform(src_pts, dst_pts)
    corrected = cv2.warpPerspective(img, M, (500, 600))
    
    # 3. 降噪处理
    denoised = cv2.bilateralFilter(corrected, 9, 75, 75)
    
    # 4. 创建ROI区域
    roi = denoised[100:400, 150:350]
    
    # 5. 添加水印
    watermark = cv2.imread("watermark.png", cv2.IMREAD_UNCHANGED)
    watermark = cv2.resize(watermark, (100, 50))
    roi_watermark = denoised[10:60, 10:110]
    alpha = watermark[:, :, 3] / 255.0
    for c in range(3):
        roi_watermark[:, :, c] = alpha * watermark[:, :, c] + (1 - alpha) * roi_watermark[:, :, c]
    
    return denoised

总结

  1. 插值选择:实时系统用最近邻,质量优先用双三次
  2. 边缘填充:反射101(BORDER_REFLECT_101)效果最自然
  3. 透视变换:确保四个点形成凸四边形
  4. 掩膜应用:结合阈值法创建精确掩膜
  5. 噪声消除
    • 椒盐噪声 → 中值滤波
    • 高斯噪声 → 高斯滤波
    • 边缘保护 → 双边滤波
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值