day29图像处理OpenCV

发布于:2025-04-19 ⋅ 阅读:(18) ⋅ 点赞:(0)

一、图像预处理

6 图像色彩空间转换

6.3灰色/BGR/HSV相互转化

  • 语法
new_img = cv.cvtColor(image, 类型)
  • 参数:
    • image:图片
    • 类型
      • cv2.COLOR_BGR2GRAY:将 BGR 图像转换为灰度图像。
      • cv2.COLOR_BGR2HSV:将 BGR 图像转换为 HSV 图像。
      • cv2.COLOR_BGR2RGB:将 BGR 图像转换为 RGB 图像。

7 彩图转灰图方法

这种做法在图像处理和计算机视觉领域非常常见。

灰度图与彩色图最大的不同就是:彩色图是由R、G、B三个通道组成,而灰度图只有一个通道,也称为单通道图像,所以彩色图转成灰度图的过程本质上就是将R、G、B三通道合并成一个通道的过程。本实验中一共介绍了三种合并方法,分别是最大值法、平均值法以及加权均值法。

7.1 最大值法

对于彩色图像的每个像素,它会从R、G、B三个通道的值中选出最大的一个,并将其作为灰度图像中对应位置的像素值。

7.2 平均值法

对于彩色图像的每个像素,它会将R、G、B三个通道的像素值全部加起来,然后再除以三,得到的平均值就是灰度图像中对应位置的像素值。

7.3 加权均值法

对于彩色图像的每个像素,它会按照一定的权重去乘以每个通道的像素值,并将其相加,得到最后的值就是灰度图像中对应位置的像素值。本实验中,权重的比例为: R乘以0.299,G乘以0.587,B乘以0.114,这是经过大量实验得到的一个权重比例,也是一个比较常用的权重比例。

所使用的权重之和应该等于1。这是为了确保生成的灰度图像素值保持在合理的亮度范围内,并且不会因为权重的比例不当导致整体过亮或过暗。

7.4 案例

import cv2 as cv
import numpy as np
# 读取图片
pig = cv.imread("./images/pig.png")
h, w, _ = pig.shape # 宽,长
# 创建灰度图
gray = np.zeros((h, w), dtype=np.uint8)
# 权重
wr, wg, wb = 0.299, 0.587, 0.114
# 遍历像素点,转化生成灰图
for i in range(h):
    for j in range(w):
        # 取最大值
        gray[i, j] = np.max(cat[i, j])
        # 取平均值
        gray[i, j] = np.mean(pig[i, j])
        # 取加权平均值--int目的是因为cv2.imwrite()函数的参数要求是uint8类型
        gray[i, j] = int(wb * pig[i, j][0] + wg * pig[i, j][1] + wr * pig[i, j][2])
cv.imshow("gray", gray)
cv.imshow("pig", pig)
cv.waitKey(0)
cv.destroyAllWindows()

8 图像二值化处理

  • 目的:将某张图像的所有像素都改成 0 或 255 。

  • 二值化的过程:就是将一张灰度图上的像素根据某种规则修改为0和maxval(maxval表示最大值,一般为255,显示白色)两种像素值

  • 特点

    • 简便:降低计算量和计算需求,加快处理速度。
    • 节约资源:二值图像占用空间远小于彩色图。
    • 边缘检测:二值化常作为边缘检测的预处理步骤,因为简化后的图易于识别出轮廓和边界。
  • 全局阈值法。

  • _,binary = cv2.threshold(img,thresh,maxval,type)
    
    • img:输入图像,要进行二值化处理的灰度图。
    • thresh:设定的阈值。
    • maxval:最大像素值
    • type阈值处理的类型。(下面在介绍)
    • 返回值:
      • 第一个值:阈值
      • 第二个值:二值化后的图像矩阵。与输入图像尺寸相同。

8.1 阈值法(type=cv2.THRESH_BINARY)

  • 原理:每一个像素点与阈值判断,小于取0,大于阈值取阈值。

8.2 反阈值法(THRESH_BINARY_INV)

  • 原理:每一个像素点与阈值判断,小于阈值取阈值,大于阈值取0。

8.3 截断阈值法(THRESH_TRUNC)

  • 原理:每一个像素点与阈值判断,大于阈值修改为阈值,小于等于阈值的部分不变。

  • 当阈值为255时,图片不发生变化。

8.4 低阈值零处理(THRESH_TOZERO)

  • 原理:像素值小于等于阈值的部分被置为0(也就是黑色),大于阈值的部分不变。

8.5 超阈值零处理(THRESH_TOZERO_INV)

  • 原理:每个像素与阈值进行比较,像素值大于阈值的部分置为0(也就是黑色),像素值小于等于阈值的部分不变。

8.6 OTSU阈值法

  • 语法: type = cv2.THRESH_OTS
  • 结合了阈值法(默认)和反阈值法
    • type = cv2.THRESH_OTS + cv2.THRESH_BINARY
  • 自动计算中最佳的阈值,所以传入的阈值无效。

OTSU算法是通过一个值将这张图分前景色和背景色(也就是灰度图中小于这个值的是一类,大于这个值的是一类。例如,如果你设置阈值为128,则所有大于128的像素点可以被视作前景,而小于等于128的像素点则被视为背景。),通过统计学方法(最大类间方差)来验证该值的合理性,当根据该值进行分割时,使用最大类间方差计算得到的值最大时,该值就是二值化算法中所需要的阈值。通常该值是从灰度图中的最小值加1开始进行迭代计算,直到灰度图中的最大像素值减1,然后把得到的最大类间方差值进行比较,来得到二值化的阈值。以下是一些符号规定:

T:阈值(决定怎么分割前景和北京

N 0 N_{0} N0:前景像素点数

N 1 N_{1} N1:背景像素点数

ω 0 \omega_{0} ω0:前景的像素点数占整幅图像的比例

ω 1 \omega_{1} ω1:背景的像素点数占整幅图像的比例

U 0 \mathcal{U_{0}} U0:前景的平均像素值

U 1 \mathcal{U_{1}} U1:背景的平均像素值

U \mathcal{U} U:整幅图的平均像素值

rows×cols:图像的行数和列数

下面举个例子,有一张大小为4×4的图片,假设阈值T为1,那么:
在这里插入图片描述

也就是这张图片根据阈值1分为了前景(像素为2的部分)和背景(像素为0)的部分,并且计算出了OTSU算法所需要的各个数据,根据上面的数据,我们给出计算类间方差的公式:
g = ω 0 ( μ 0 − μ ) 2 + ω 1 ( μ 1 − μ ) 2 g=\omega_{0}(\mu_{0}-\mu)^{2}+\omega_{1}(\mu_{1}-\mu)^{2} g=ω0(μ0μ)2+ω1(μ1μ)2
g就是前景与背景两类之间的方差,这个值越大,说明前景和背景的差别就越大,效果就越好。OTSU算法就是在灰度图的像素值范围内遍历阈值T,使得g最大,基本上双峰图片的阈值T在两峰之间的谷底。

8.7 自适应二值化

与二值化算法相比,自适应二值化更加适合用在明暗分布不均的图片

  • 语法:只有一个返回值
new_img = cv2.adaptiveThreshold(image, 255, adaptiveMethod=cv2.ADAPTIVE_THRESH_MEAN_C, 
thresholdType=cv2.THRESH_BINARY, blockSize=7, c=10)

其中各个参数的含义如下:

  • maxval:最大阈值

  • adaptiveMethod:小区域阈值的计算方式:

  • ADAPTIVE_THRESH_MEAN_C:小区域内取均值(方法1)

  • ADAPTIVE_THRESH_GAUSSIAN_C:小区域内加权求和,权重是个高斯核(方法2)

  • thresholdType:二值化方法,只能使用THRESH_BINARY、THRESH_BINARY_INV,也就是阈值法和反阈值法

  • blockSize:处理核大小

  • c:最终阈值等于小区域计算出的阈值再减去此值

下面介绍一下这两种方法。

1. 取均值
  • 每一个像素点的计算过程:
    • 待计算像素点为中心,取3*3的区域(不够就使用边缘填充补齐)
    • 然后卷积核与区域一一对应相乘再累加 -C(如下黑图)
      在这里插入图片描述
2. 加权求和

具体原理,这里不需要理解。

某像素点的阈值计算过程如下图所示:

在这里插入图片描述

8.9 案例

import cv2 as cv

img = cv.imread('./images/flower.png')
img = cv.resize(img, (360, 360))
# 灰度化
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
# 阈值发
_, binary = cv.threshold(gray, 127,255,cv.THRESH_BINARY)
# 反阈值法
_, binary2 = cv.threshold(gray, 127,255,cv.THRESH_BINARY_INV)
# 截断阈值法
_, binary3 = cv.threshold(gray, 127,255,cv.THRESH_TRUNC)
# 低阈值0处理法
_, binary4 = cv.threshold(gray, 127,255,cv.THRESH_TOZERO)
# 高阈值0处理法
_, binary5 = cv.threshold(gray, 127,255,cv.THRESH_TOZERO_INV)
# OTSU阈值法
_, binary6 = cv.threshold(gray, 127,255,cv.THRESH_OTSU+cv.THRESH_BINARY)
# 自适应二值法-取均值
binary7 = cv.adaptiveThreshold(gray, 255, cv.ADAPTIVE_THRESH_MEAN_C, cv.THRESH_BINARY, 5, 2)
# 自适应二值法-加权平均值
binary8 = cv.adaptiveThreshold(gray, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 5, 2)

cv.imshow('binary', binary8)
cv.imshow('img', img)
cv.waitKey(0)
cv.destroyAllWindows()

网站公告

今日签到

点亮在社区的每一天
去签到