图像分类

安装颜色对图像进行分类,可以分为二值图像,灰度图像和彩色图像。

  1. 二值图像:只有黑色和白色两种颜色的图像。每个像素点可以用0/1表示,0表示黑色,1表示白色。
  2. 灰度图像:只有灰度的图像。每个像素点用8bit数字[0,255]表示灰度,如:0表示纯黑,255表示纯白。
  3. 彩色图像:彩色图像通常采用红色(R),绿色(G)和蓝色(B)三个彩色通道的组合表示。

简单阈值

对于每个像素,应用相同的阈值。如果像素值小于阈值,则将其设置为0,否则将其设置为最大值。

cv.threshold(src,thresh,maxval,type,dst)

  • src:变换操作的输入图像,ndarray二维数组,必须是单通道灰度图像。
  • thresh:阈值,取值范围0~255.
  • maxval:填充色,取值范围0~255,一般取255.
  • type:变换类型
  • dst:返回阈值变换的输出图像。

type值说明

  • cv.THRESH_BINARY:表示大于阈值时置255,否则置0.
  • cv.THRESH_BINARY_INV:表示大于阈值时置0,否则置255.
  • cv.THRESH_TRUNC:表示大于阈值时置为阈值thresh,否则不变(保持原色)
  • cv.THRESH_TOZERO:表示大于阈值时不变(保持原色),否则置0。
  • cv.THRESH_TOZERO_INV:表示大于阈值时置0,否则不变(保持原色)。
  • cv.THRESH_OTSU:表示使用OTSU算法选择阈值。
import cv2 as cv
from matplotlib import pyplot as plt

img=cv.imread('./images/lena.jpeg',0)
ret,binary=cv.threshold(img,127,255,cv.THRESH_BINARY)
ret,binary_inv=cv.threshold(img,127,255,cv.THRESH_BINARY_INV)
ret,trunc=cv.threshold(img,127,255,cv.THRESH_TRUNC)
ret,tozero=cv.threshold(img,127,255,cv.THRESH_TOZERO)
ret,tozero_inv=cv.threshold(img,127,255,cv.THRESH_TOZERO_INV)

titles=["original","binary","binary_inv","trunc","tozero","tozero_inv"]
images=[img,binary,binary_inv,trunc,tozero,tozero_inv]
for i in range(6):
    plt.subplot(2,3,i+1)
    plt.imshow(images[i],'gray')
    plt.title(titles[i])
    plt.xticks([])
    plt.yticks([])
plt.show()

结果:

 自适应阈值

上面使用全局值作为阈值,可能并非所用情况都很好。如果图像在不同区域具有不同的光照条件。在这种情况下,自适应阈值可以提供帮助。在此,算法基于像素周围的小区域确定像素的阈值。因此,对于同一图像的不同区域,获得不同的阈值,这为光照强度变换的图像提供了更好的结果。

除了上述参数外,方法cv.adaptiveThreshold还包括三个输入参数:

adaptiveMethod:指定计算阈值的方法

  • cv.ADAPTIVE_THRESH_MEAN_C:阈值取自相邻区域的平均值。
  • cv.ADAPTIVE_THRESH_GAUSSIAN_C:阈值取自相邻区域的加权和,权重为一个高斯窗口。

Block Size:领域大小(用来计算阈值的区域大小)

C:这就是一个常数,阈值就等于平均值或者加权平均值减去这个常数。

import cv2 as cv
import matplotlib.pyplot as plt

img=cv.imread('./images/lena.jpeg',0)
img=cv.medianBlur(img,5)
ret,thresh1=cv.threshold(img,127,255,cv.THRESH_BINARY)
thresh2=cv.adaptiveThreshold(img,255,cv.ADAPTIVE_THRESH_MEAN_C,cv.THRESH_BINARY,11,2)
thresh3=cv.adaptiveThreshold(img,255,cv.ADAPTIVE_THRESH_GAUSSIAN_C,cv.THRESH_BINARY,11,2)

titles=["original","binary(v=127)","adaptive mean","adaptive gaussian"]
images=[img,thresh1,thresh2,thresh3]

for i in range(4):
    plt.subplot(2,2,i+1)
    plt.imshow(images[i],'gray')
    plt.title(titles[i])
    plt.xticks([])
    plt.yticks([])
plt.show()

结果:

 Otsu的二值化

在全局阈值化中,使用任意选择的值作为阈值。相反,Otsu的方法避免了必须选择一个值并自动确定它的情况。

考虑仅具有两个不同图像值的图像(双峰图像),其中直方图将仅包含两个峰。一个好的阈值应该在这两个值的中间。类似地,Otsu的方法从图像直方图中确定最佳全局阈值。

 在第一种情况下,采用值为127的全局阈值。在第二种情况下,直接采用Otsu阈值法。在第三种情况下,首先使用5x5高斯核对图像进行滤波以去除噪声,然后应用Otsu阈值处理。

import cv2 as cv
from matplotlib import pyplot as plt

img=cv.imread('./images/lena.jpeg',0)
# 全局阈值
ret1,th1=cv.threshold(img,127,255,cv.THRESH_BINARY)
# Otsu阈值
ret2,th2=cv.threshold(img,0,255,cv.THRESH_BINARY+cv.THRESH_OTSU)
# 高斯滤波后在采用Otsu阈值
blur=cv.GaussianBlur(img,(5,5),0)
ret3,th3=cv.threshold(img,0,255,cv.THRESH_BINARY+cv.THRESH_OTSU)
images=[img,0,th1,
        img,0,th2,
        blur,0,th3]
titles=["original","histogram","global thresholdding(v=127)",
        "original","histogram","otsu's thresholding",
        "gaussian filter","histogram","otsu's thresholding"]
for i in range(3):
    plt.subplot(3,3,i*3+1)
    plt.imshow(images[i*3],'gray')
    plt.title(titles[i*3])
    plt.xticks([])
    plt.yticks([])
    plt.subplot(3, 3, i * 3 + 2)
    plt.hist(images[i * 3].ravel(), 256)
    plt.title(titles[i * 3+1])
    plt.xticks([])
    plt.yticks([])
    plt.subplot(3, 3, i * 3 + 3)
    plt.imshow(images[i * 3+2], 'gray')
    plt.title(titles[i * 3+2])
    plt.xticks([])
    plt.yticks([])
plt.show()

 

 posted on 2024-05-02 21:58  会飞的金鱼  阅读(49)  评论(0)    收藏  举报