《零基础入门AI:图像翻转变换到二值化处理(OpenCV预处理)》_opencv是朝哪里转的
一、图像翻转(镜像旋转)
图像翻转是沿水平或垂直轴镜像反转图像的操作,类似于照镜子。这种操作在数据增强和图像校正中非常有用。
翻转类型:
- 水平翻转:沿垂直轴翻转(左右互换)
- 垂直翻转:沿水平轴翻转(上下互换)
- 双向翻转:同时进行水平和垂直翻转
API: cv2.flip(img,flipcode)
关键参数说明:cv2.flip()
函数的第二个参数决定翻转方向:1=水平,0=垂直,-1=双向。
import cv2import numpy as np# 读取图像img = cv2.imread(\'image.jpg\')# 水平翻转(1表示水平轴 沿y轴)flip_horizontal = cv2.flip(img, 1)# 垂直翻转(0表示垂直轴 沿x轴)flip_vertical = cv2.flip(img, 0)# 双向翻转(-1表示两个轴)flip_both = cv2.flip(img, -1)
二、 单点旋转
1. 基本概念解析
单点旋转指在二维或三维空间中,一个点围绕固定中心点按特定角度转动的操作。这种变换保持点到中心的距离不变,仅改变其方位。
关键参数:
- 旋转中心:变换的基准点(不动点)
- 旋转角度:转动的大小(度数或弧度)
- 旋转方向:顺时针或逆时针
- 旋转半径:点到中心的距离(变换中保持不变)
2. 数学原理推导与公式
首先我们以最简单的一个点的旋转为例子,且以最简单的情况举例,令旋转中心为坐标系中心O(0,0),假设有一点P0(x0,y0)P_{0}(x_{0},y_{0})P0(x0,y0),P0P_{0}P0离旋转中心O的距离为r,OP0OP_{0}OP0与坐标轴x轴的夹角为α\\alphaα,P0P_{0}P0绕O顺时针旋转θ\\thetaθ角后对应的点为P(x,y)P(x,y)P(x,y)。
那么我们可以得到如下关系:
x0=r×cosαx_{0}=r\\times\\cos\\alphax0=r×cosα
y0=r×sinαy_{0}=r\\times\\sin\\alphay0=r×sinα
x=r×cos(α−θ)=rcosαcosθ+rsinαsinθ=x0cosθ+y0sinθx=r\\times\\cos(\\alpha-\\theta)=r\\cos\\alpha\\cos\\theta+r\\sin\\alpha\\sin\\theta=x_{0}\\cos\\theta+y_{0}\\sin\\thetax=r×cos(α−θ)=rcosαcosθ+rsinαsinθ=x0cosθ+y0sinθ
y=r×sin(α−θ)=rsinαcosθ−rcosαsinθ=−x0sinθ+y0cosθy=r\\times\\sin(\\alpha-\\theta)=r\\sin\\alpha\\cos\\theta-r\\cos\\alpha\\sin\\theta=-x_{0}\\sin\\theta+y_{0}\\cos\\thetay=r×sin(α−θ)=rsinαcosθ−rcosαsinθ=−x0sinθ+y0cosθ
用矩阵来表示就是
[xy]=[cosθ sinθ−sinθ cosθ]∗[x0y0]\\left[\\begin{array}{l l}{{x}}\\\\{{y}}\\end{array}\\right]=\\left[\\begin{array}{l l}{{\\cos\\theta~~~~\\sin\\theta}}\\\\{{-\\sin\\theta~~~~\\cos\\theta}}\\\\\\end{array}\\right]*\\left[\\begin{array}{c}{{x_{0}}}\\\\{{y_{0}}}\\end{array}\\right][xy]=[cosθ sinθ−sinθ cosθ]∗[x0y0]
然而,在OpenCV中,旋转时是以图像的左上角为旋转中心,且以逆时针为正方向,因此上面的例子中其实是个负值,那么该矩阵可写为:
[xy]=[cosθ −sinθsinθ cosθ]∗[x0y0]\\left[\\begin{array}{l l}{{x}}\\\\{{y}}\\end{array}\\right]=\\left[\\begin{array}{l l}{{\\cos\\theta~~~~-\\sin\\theta}}\\\\{{\\sin\\theta~~~~\\cos\\theta}}\\\\\\end{array}\\right]*\\left[\\begin{array}{c}{{x_{0}}}\\\\{{y_{0}}}\\end{array}\\right][xy]=[cosθ −sinθsinθ cosθ]∗[x0y0]
其中,
[cosθ −sinθsinθ cosθ]\\left[\\begin{array}{l l}{{\\cos\\theta~~~~-\\sin\\theta}}\\\\{{\\sin\\theta~~~~\\cos\\theta}}\\\\\\end{array}\\right][cosθ −sinθsinθ cosθ]
也被称作旋转矩阵。然而我们所要的不仅仅是可以围绕图像左上角进行旋转,而是可以围绕任意点进行旋转。那么我们可以将其转化成绕原点的旋转,其过程为:
- 首先将旋转点移到原点
- 按照上面的旋转矩阵进行旋转得到新的坐标点
- 再将得到的旋转点移回原来的位置
也就是说,在以任意点为旋转中心时,除了要进行旋转之外,还要进行平移操作。那么当点经过平移后得到P点时,如下图所示:
那么我们就可以得到:
x=x0+txx=x_{0}+t_{x}x=x0+tx
y=y0+tyy=y_{0}+t_{y}y=y0+ty
写成矩阵的形式为:
[xy1]=[1 0 tx0 1 ty0 0 1]∗[x0y01]\\left[\\begin{array}{l l l}{{x}}\\\\{{y}}\\\\{1}\\end{array}\\right]=\\left[\\begin{array}{c}{{1~~~~0~~~~t_{x}}}\\\\{{0~~~~1~~~~t_{y}}}\\\\{{0~~~~0~~~~1}}\\end{array}\\right]*\\left[\\begin{array}{c}{{x_0}}\\\\{{y_0}}\\\\{1}\\end{array}\\right]xy1=1 0 tx0 1 ty0 0 1∗x0y01
于是
[1 0 tx0 1 ty0 0 1]\\left[\\begin{array}{l l l}{{1~~~~0~~~~t_{x}}}\\\\{{0~~~~1~~~~t_{y}}}\\\\{{0~~~~0~~~~1}}\\end{array}\\right]1 0 tx0 1 ty0 0 1
也被叫做平移矩阵,相反的,从P移到点时,其平移矩阵为:
[10− tx01− ty001]\\left[\\begin{array}{l l l}{1}&{0}&{-\\,t_{x}}\\\\ {0}&{1}&{-\\,t_{y}}\\\\ {0}&{0}&{1}\\end{array}\\right]100010−tx−ty1
我们将原始的旋转矩阵也扩展到3*3的形式:
[xy1]=[cosθ−sinθ0sinθcosθ0001]∗[x0y01]\\begin{array}{l l l}{{\\left[\\begin{array}{c}{{x}}\\\\{{y}}\\\\{1} \\end{array}\\right]=\\left[\\begin{array}{c c c}{{\\cos\\theta}}&{{-\\sin\\theta}}&{{0}}\\\\ {{\\sin\\theta}}&{{\\cos\\theta}}&{{0}}\\\\ {{0}}&{{0}}&{{1}}\\end{array}\\right]*\\left[\\begin{array}{c}{{x_{0}}}\\\\{{y_{0}}}\\\\{{1}}\\end{array}\\right]}}\\end{array}xy1=cosθsinθ0−sinθcosθ0001∗x0y01
从平移和旋转的矩阵可以看出,3x3矩阵的前2x2部分是和旋转相关的,第三列与平移相关。有了上面的表达式之后,我们就可以得到二维空间中绕任意点旋转的旋转矩阵了,只需要将旋转矩阵先左乘
[1 0 tx0 1 ty0 0 1]\\left[\\begin{array}{l l l}{{1~~~~0~~~~t_{x}}}\\\\{{0~~~~1~~~~t_{y}}}\\\\{{0~~~~0~~~~1}}\\end{array}\\right]1 0 tx0 1 ty0 0 1
,再右乘
[10− tx01− ty001]\\left[\\begin{array}{l l l}{1}&{0}&{-\\,t_{x}}\\\\ {0}&{1}&{-\\,t_{y}}\\\\ {0}&{0}&{1}\\end{array}\\right]100010−tx−ty1
即可得到最终的矩阵,其结果为:
M=[cosθ −sinθ (1−cosθ)tx+ty∗sinθsinθ cosθ (1−cosθ)ty+tx∗sinθ0 0 1]M=\\left[\\begin{array}{l l l}{{\\cos\\theta~~-\\sin\\theta~~(1-\\cos\\theta)t_{x}+t_{y}*\\sin\\theta}}\\\\{{\\sin\\theta~~~\\cos\\theta~~~~~(1-\\cos\\theta)t_{y}+t_{x}*\\sin\\theta}}\\\\{{0~~~~~~~~~~~~~0~~~~~~~~~~~~~1}}\\end{array}\\right]M=cosθ −sinθ (1−cosθ)tx+ty∗sinθsinθ cosθ (1−cosθ)ty+tx∗sinθ0 0 1
于是我们就可以根据这个矩阵计算出图像中任意一点绕某点旋转后的坐标了,这个矩阵学名叫做仿射变换矩阵,而仿射变换是一种二维坐标到二维坐标之间的线性变换,也就是只涉及一个平面内二维图形的线性变换,图像旋转就是仿射变换的一种。
三、图像仿射变换
仿射变换是保持图像中直线平行性的几何变换,包括旋转、平移和缩放三种基本操作。
1. 核心概念剖析
图像仿射变换是保持直线平行性的二维几何变换,通过线性变换和平移组合实现。它可以将矩形映射为任意平行四边形,但保持直线仍是直线。
五大基本操作:
- 平移:图像整体移动
- 旋转:围绕中心点转动
- 缩放:图像按比例放大缩小
- 剪切:图像沿轴向倾斜变形
- 翻转:图像镜像反转
2. 仿射变换的基本原理
-
线性变换
-
二维空间中,图像点坐标为(x,y),仿射变换的目标是将这些点映射到新的位置 (x’,y’)。
-
为了实现这种映射,通常会使用一个矩阵乘法的形式:(类似于y=kx+b)
-
a,b,c,d 是线性变换部分的系数,控制旋转、缩放和剪切。
-
tx,ty 是平移部分的系数,控制图像在平面上的移动。
-
输入点的坐标被扩展为齐次坐标形式[x,y,1],以便能够同时处理线性变换和平移。
-
API:cv2.warpAffine(img,M,dsize)
-
img:输入图像。
-
M:2x3的变换矩阵,类型为
np.float32
。 -
dsize:输出图像的尺寸,形式为
(width,height)
。
3. 图像旋转
图像旋转围绕一个中心点按指定角度转动图像。旋转后图像大小可能会改变,需要调整画布大小。
API:cv2.getRotationMatrix2D(center,angle,scale) 【获取旋转矩阵】
- center:旋转中心点的坐标,格式为
(x,y)
,也可以不使用中心点。 - angle:旋转角度,单位为度,正值表示逆时针旋转负值表示顺时针旋转。
- scale:缩放比例,若设为1,则不缩放。
- 返回值:M,2x3的旋转矩阵。
# 获取图像高度和宽度height, width = img.shape[:2]# 计算图像中心点center = (width // 2, height // 2)# 获取旋转矩阵:中心点,旋转角度(逆时针45°),缩放因子M = cv2.getRotationMatrix2D(center, 45, 1.0)# 仿射变换函数 cv2.warpAffine(img,M,dsize) 应用旋转矩阵rotated_img = cv2.warpAffine(img, M, (width, height))
4. 图像平移
图像平移是将图像沿X轴和Y轴方向移动指定距离的操作,常用于图像对齐。
原理:
假设我们有一个点 P(x,y)P(x,y)P(x,y),希望将其沿x轴方向平移txt_xtx*个单位,沿y轴方向平移tyt_yty个单位到新的位置P′(x′,y′)P′(x′,y′)P′(x′,y′),那么平移公式如下:
x′=x+txx′=x+txx′=x+tx
y′=y+tyy′=y+tyy′=y+ty
在矩阵形式下,该变换可以表示为:
这里的txt_xtx和tyt_yty分别代表在x轴和y轴上的平移量。
# 定义平移量 X方向平移100像素,Y方向平移50像素tx = 100ty = 50# 获取平移矩阵M = np.float32([[1, 0, tx], [0, 1, ty]])# 仿射变换 cv2.warpAffine(img,M,dsize) 应用平移变换translated_img = cv2.warpAffine(img, M, (width, height))
5. 图像缩放
图像缩放改变图像的尺寸大小,可以等比例缩放或指定新尺寸。
原理:
假设要把图像的宽高分别缩放为0.5和0.8,那么对应的缩放因子sx=0.5
,sy=0.8
。
点P(x,y)P(x,y)P(x,y)对应到新的位置P′(x′,y′)P\'(x\',y\')P′(x′,y′),缩放公式为:
x′=sx∗xx′=s_x*xx′=sx∗x
y′=sy∗yy′=s_y*yy′=sy∗y
在矩阵形式下,该变换可以表示为:
相较于图像旋转中只能等比例的缩放,图像缩放更加灵活,可以在指定方向上进行缩放。
# 1.# 等比例缩小到原来的一半resized_half = cv2.resize(img, None, fx=0.5, fy=0.5)# 指定新尺寸为400x300像素resized_custom = cv2.resize(img, (400, 300))# 2.# 定义缩放量sx = 0.5sy = 0.8# 定义缩放矩阵M = np.float32([[sx, 0, 0], [0, sy, 0]])# 仿射变换 cv2.warpAffine(img,M,dsize) resized_img = cv2.warpAffine(img,M,(weight,height))
6. 总结
变换矩阵形式
单点旋转和图像仿射变换差异
四、图像色彩空间转换
色彩空间是表示颜色的数学模型,不同的色彩空间适用于不同的图像处理任务。
1. RGB颜色空间
RGB是最常用的色彩空间,通过红(Red)、绿(Green)、蓝(Blue)三个通道的组合表示颜色:
- 每个通道值范围:0-255
- 黑色:(0,0,0),白色:(255,255,255)
- 在OpenCV中存储顺序为BGR(蓝绿红)
2. 颜色加法操作
你可以使用OpenCV的cv.add()
函数把两幅图像相加,或者可以简单地通过numpy操作添加两个图像,如res = img1 + img2。两个图像尺寸相同和通道数相同。
注:OpenCV加法和Numpy加法之间存在差异。OpenCV的加法是饱和操作,而Numpy添加是模运算( % )。
# 创建两个纯色图像red_img = np.zeros((300, 300, 3), dtype=np.uint8)red_img[:, :] = (0, 0, 255) # 纯红色(BGR格式)green_img = np.zeros((300, 300, 3), dtype=np.uint8)green_img[:, :] = (0, 255, 0) # 纯绿色# 简单加法(可能导致值超过255)simple_add = cv2.add(red_img, green_img)# numpy 直接相加 取模运算 对256取模 250 + 10dst2 = red_img + green_img# 加权加法(图像融合) cv2.addWeighted(src1,alpha,src2,deta,gamma)# alpha-> src1的权重 deta-> src2的权重 gamma-> 亮度blended = cv2.addWeighted(red_img, 0.7, green_img, 0.3, 0)
3. HSV颜色空间
HSV色彩空间更符合人类感知颜色的方式:
- H (Hue):色相,表示颜色类型(0-180)
- S (Saturation):饱和度,表示颜色鲜艳程度(0-255)
- V (Value):明度,表示颜色亮度(0-255)
应用场景:HSV空间常用于颜色检测和分割,因为色相(H)通道对光照变化不敏感。
4.图像颜色空间的转换
API:cv2.cvtColor(img,code)
img
:输入图像,可以是一个Numpy数组绘着一个OpenCV的Mat对象Mat
是一个核心的数据结构,主要用于存储图像和矩阵数据。在 Python 中使用 OpenCV 时,通常直接处理的是 NumPy 数组,cv2
模块自动将Mat
对象转换为 NumPy 数组。二者之间的转换是透明且自动完成的。例如,当你使用cv2.imread()
函数读取图像时,返回的是一个 NumPy 数组,但在C++中则是Mat
对象。
code
:指定转换的类型,可以使用预定义的转换代码。- 例如
cv2.COLOR_RGB2GRAY
表示从RGB到灰度图像的转换。
- 例如
# 将图像从BGR转换到HSV色彩空间hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)# 将图像从BGR转换到灰度图gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 将图像从HSV转换回BGRbgr_img = cv2.cvtColor(hsv_img, cv2.COLOR_HSV2BGR)
五、灰度实验
灰度图像是仅包含亮度信息的单通道图像,相比彩色图像减少2/3的数据量,处理速度更快。
灰度化方法
-
最大值法:取RGB三个通道中的最大值
gray_max = np.max(img, axis=2)
import cv2import numpy as np# 读图pig = cv2.imread(\'../images/pig.png\')shape = pig.shape #( h, w, c )# 创建一个相同大小的黑色图片img = np.zeros((shape[0], shape[1]), dtype=\'uint8\')# 循环遍历 每一行 img[0, 0, 0]for i in range(shape[0]): # [0][0][0] [0][0][1] [0][0][2] for j in range(shape[1]): img[i,j] = max(pig[i,j,0], pig[i,j,1], pig[i,j,2])cv2.imshow(\'gray_max\', img)cv2.waitKey(0)cv2.destroyAllWindows()
-
平均值法:取RGB三个通道的平均值
gray_mean = np.mean(img, axis=2)
import cv2import numpy as np# 读图pig = cv2.imread(\'../images/pig.png\')shape = pig.shape #( h, w, c )# 创建一个相同大小的黑色图片img = np.zeros((shape[0], shape[1]), dtype=\'uint8\')# 循环遍历 每一行 img[0, 0, 0]for i in range(shape[0]): # [0,0,0] [0,0,1] [0,0,2] for j in range(shape[1]): # int(): 转为更大的数据类型,防止溢出 img[i,j] = (int(pig[i,j,0])+ int(pig[i,j,1])+int(pig[i,j,2])) // 3cv2.imshow(\'gray_avg\', img)cv2.waitKey(0)cv2.destroyAllWindows()
-
加权平均法:考虑人眼对不同颜色的敏感度
# 标准权重:红30%,绿59%,蓝11%gray_weighted = 0.299 * img[:,:,2] + 0.587 * img[:,:,1] + 0.114 * img[:,:,0]
import cv2import numpy as np# 读图pig = cv2.imread(\'../images/pig.png\')shape = pig.shape #( h, w, c )# 创建一个相同大小的黑色图片img = np.zeros((shape[0], shape[1]), dtype=\'uint8\')#定义权重wb, wg, wr = 0.114, 0.587, 0.299# 循环遍历 每一行 img[0, 0, 0]for i in range(shape[0]): # [0,0,0] [0,0,1] [0,0,2] for j in range(shape[1]): # int(): 转为更大的数据类型,防止溢出 img[i,j] = round(pig[i,j,0] * wb+ pig[i,j,1] * 0.587+pig[i,j,2] * 0.299)cv2.imshow(\'gray_weight\', img)cv2.waitKey(0)cv2.destroyAllWindows()
灰度极端值
# 创建纯黑图像(所有像素值为0)black_image = np.zeros((300, 300), dtype=np.uint8)# 创建纯白图像(所有像素值为255)white_image = np.full((300, 300), 255, dtype=np.uint8)
人眼感知特点:人眼对绿色最敏感,对蓝色最不敏感,因此加权平均法得到的灰度图视觉效果最自然。
六、图像二值化处理
二值化将灰度图像转换为仅包含纯黑(0)和纯白(255)两种值的图像,是许多图像分析任务的基础。
API:cv2.threshold(img,thresh,maxval,type)
img
:输入图像,要进行二值化处理的灰度图。thresh
:设定的阈值。当像素值大于(或小于,取决于阈值类型)thresh
时,该像素被赋予的值。type
:阈值处理的类型。- 返回值:
- 第一个值(通常用下划线表示):计算出的阈值,若使用自适应阈值法,会根据算法自动计算出这个值。
- 第二个值(binary):二值化后的图像矩阵。与输入图像尺寸相同。
1. 基础二值化方法
- 阈值法(THRESH_BINARY):通过设置一个阈值,将灰度图中的每一个像素值与该阈值进行比较,小于等于阈值的像素就被设置为0(通常代表背景),大于阈值的像素就被设置为maxval(通常代表前景)。对于我们的8位图像(0~255)来说,通常是设置为255。
- 反阈值法(THRESH_BINARY_INV):与阈值法相反。反阈值法是当灰度图的像素值大于阈值时,该像素值将会变成0(黑),当灰度图的像素值小于等于阈值时,该像素值将会变成maxval。
- 截断阈值法(THRESH_TRUNC):截断阈值法,指将灰度图中的所有像素与阈值进行比较,像素值大于阈值的部分将会被修改为阈值,小于等于阈值的部分不变。换句话说,经过截断阈值法处理过的二值化图中的最大像素值就是阈值。
- 低阈值零处理(THRESH_TOZERO):像素值小于等于阈值的部分被置为0(也就是黑色),大于阈值的部分不变。
- 超阈值零处理(THRESH_TOZERO_INV):将灰度图中的每个像素与阈值进行比较,像素值大于阈值的部分置为0(也就是黑色),像素值小于等于阈值的部分不变。
2.高级二值化方法
灰度图直方图:直方图是一个柱状图,其中 x 轴表示灰度级(从 0 到 255),y 轴表示对应灰度级在图像中出现的次数(频率)。每个柱子的高度代表该灰度级在图像中出现的像素数量。
双峰图:双峰图片就是指灰度图的直方图上有两个峰值,直方图就是对灰度图中每个像素值的点的个数的统计图,如下图所示。
OTSU算法:通过一个值将这张图分前景色和背景色(也就是灰度图中小于这个值的是一类,大于这个值的是一类。例如,如果你设置阈值为128,则所有大于128的像素点可以被视作前景,而小于等于128的像素点则被视为背景。),通过统计学方法(最大类间方差)来验证该值的合理性,当根据该值进行分割时,使用最大类间方差计算得到的值最大时,该值就是二值化算法中所需要的阈值。通常该值是从灰度图中的最小值加1开始进行迭代计算,直到灰度图中的最大像素值减1,然后把得到的最大类间方差值进行比较,来得到二值化的阈值。
OTSU阈值法:cv2.THRESH_OTS 并不是一个有效的阈值类型或标。THRESH_OTSU
本身并不是一个独立的阈值化方法,而是与 OpenCV 中的二值化方法结合使用的一个标志。具体来说,THRESH_OTSU
通常与 THRESH_BINARY
或 THRESH_BINARY_INV
结合使用。在实际应用中,如果你使用 THRESH_OTSU
标志但没有指定其他二值化类型,默认情况下它会与 THRESH_BINARY
结合使用。也就是说,当你仅指定了 cv2.THRESH_OTSU
,实际上等同于同时指定了 cv2.THRESH_BINARY + cv2.THRESH_OTSU
。
自适应二值化:自适应二值化方法会对图像中的所有像素点计算其各自的阈值,这样能够更好的保留图片里的一些信息。
-
API:cv2.adaptiveThreshold(image_np_gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 7, 10)
-
maxval
:最大阈值,一般为255adaptiveMethod
:小区域阈值的计算方式:ADAPTIVE_THRESH_MEAN_C
:小区域内取均值ADAPTIVE_THRESH_GAUSSIAN_C
:小区域内加权求和,权重是个高斯核thresholdType
:二值化方法,只能使用THRESH_BINARY、THRESH_BINARY_INV,也就是阈值法和反阈值法blockSize
:选取的小区域的面积(奇数),如7就是7*7的小块。c
:最终阈值等于小区域计算出的阈值再减去此值,从 (计算的平均值或加权平均值中减去的常数)。
3. 基础阈值方法示例
import cv2# 读图flower = cv2.imread(\'../images/flower.png\')flower = cv2.resize(flower, (360, 360))# 灰度化处理gray_img = cv2.cvtColor(flower, cv2.COLOR_BGR2GRAY)# 应用不同阈值方法# 阈值法_, binary_basic = cv2.threshold(gray_img, 127, 255, cv2.THRESH_BINARY) # 反阈值法_, binary_inv = cv2.threshold(gray_img, 127, 255, cv2.THRESH_BINARY_INV) # 截断阈值法_, binary_trunc = cv2.threshold(gray_img, 127, 255, cv2.THRESH_TRUNC) # 低阈值零处理法_, binary_tozero = cv2.threshold(gray_img, 127, 255, cv2.THRESH_TOZERO) # 超阈值零处理法_, binary_tozero_inv = cv2.threshold(gray_img, 127, 255, cv2.THRESH_TOZERO_INV)
4. 高级二值化方法
# OTSU自动阈值法(适合双峰直方图图像)#默认结合 cv2.THRESH_BINARY cv2.THRESH_OTSU = cv2.THRESH_OTSU + cv2.THRESH_BINARY_, otsu_binary = cv2.threshold(gray_img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)# 自适应阈值法 小区域计算 必须结合阈值法 或 反阈值法(适合光照不均的图像)# 均值法adaptive_mean = cv2.adaptiveThreshold(gray_img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2)# 高斯加权法adaptive_gauss = cv2.adaptiveThreshold(gray_img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)
5. 阈值方法对比
七、图像预处理流程示例
实际应用中,通常会组合多种预处理技术:
def preprocess_image(image_path): # 1. 读取图像 img = cv2.imread(image_path) # 2. 调整大小 img = cv2.resize(img, (800, 600)) # 3. 转换为灰度图 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 4. 高斯模糊降噪 blurred = cv2.GaussianBlur(gray, (5, 5), 0) # 5. 自适应二值化 binary = cv2.adaptiveThreshold(blurred, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2) return binary