[Python图像处理] 三十一.图像点运算处理两万字详细总结(灰度化处理、阈值化处理)

该系列文章是讲解Python OpenCV图像处理知识,前期主要讲解图像入门、OpenCV基础用法,中期讲解图像处理的各类算法,包括图像锐化算子、图像加强技术、图像分割等,后期结合深度学习研究图像识别、图像分类应用。但愿文章对您有所帮助,若是有不足之处,还请海涵~python

前面一篇文章介绍了图像量化及采样处理,这篇文章将结合做者研究民族服饰及文化图腾识别,详细讲解图像点运算,包括灰度化处理、灰度线性变换、灰度非线性变换、阈值化处理,万字长文吐血整理,但愿对您有所帮助。同时,该部分知识均为做者查阅资料撰写总结,而且开设成了收费专栏,为小宝赚点奶粉钱,感谢您的抬爱。固然若是您是在读学生或经济拮据,能够私聊我给你每篇文章开白名单,或者转发原文给你,更但愿您能进步,一块儿加油喔~git

该系列在github全部源代码:github

前文参考:
[Python图像处理] 一.图像处理基础知识及OpenCV入门函数
[Python图像处理] 二.OpenCV+Numpy库读取与修改像素
[Python图像处理] 三.获取图像属性、兴趣ROI区域及通道处理
[Python图像处理] 四.图像平滑之均值滤波、方框滤波、高斯滤波及中值滤波
[Python图像处理] 五.图像融合、加法运算及图像类型转换
[Python图像处理] 六.图像缩放、图像旋转、图像翻转与图像平移
[Python图像处理] 七.图像阈值化处理及算法对比
[Python图像处理] 八.图像腐蚀与图像膨胀
[Python图像处理] 九.形态学之图像开运算、闭运算、梯度运算
[Python图像处理] 十.形态学之图像顶帽运算和黑帽运算
[Python图像处理] 十一.灰度直方图概念及OpenCV绘制直方图
[Python图像处理] 十二.图像几何变换之图像仿射变换、图像透视变换和图像校订
[Python图像处理] 十三.基于灰度三维图的图像顶帽运算和黑帽运算
[Python图像处理] 十四.基于OpenCV和像素处理的图像灰度化处理
[Python图像处理] 十五.图像的灰度线性变换
[Python图像处理] 十六.图像的灰度非线性变换之对数变换、伽马变换
[Python图像处理] 十七.图像锐化与边缘检测之Roberts算子、Prewitt算子、Sobel算子和Laplacian算子
[Python图像处理] 十八.图像锐化与边缘检测之Scharr算子、Canny算子和LOG算子
[Python图像处理] 十九.图像分割之基于K-Means聚类的区域分割
[Python图像处理] 二十.图像量化处理和采样处理及局部马赛克特效
[Python图像处理] 二十一.图像金字塔之图像向下取样和向上取样
[Python图像处理] 二十二.Python图像傅里叶变换原理及实现
[Python图像处理] 二十三.傅里叶变换之高通滤波和低通滤波
[Python图像处理] 二十四.图像特效处理之毛玻璃、浮雕和油漆特效
[Python图像处理] 二十五.图像特效处理之素描、怀旧、光照、流年以及滤镜特效
[Python图像处理] 二十六.图像分类原理及基于KNN、朴素贝叶斯算法的图像分类案例
[Python图像处理] 二十七.OpenGL入门及绘制基本图形(一)
[Python图像处理] 二十八.OpenCV快速实现人脸检测及视频中的人脸
[Python图像处理] 二十九.MoviePy视频编辑库实现抖音短视频剪切合并操做
[Python图像处理] 三十.图像量化及采样处理万字详细总结(推荐)





























算法


图像的点运算是指对图像中的每一个像素依次进行灰度变换的运算,主要用于改变一幅图像的灰度分布范围,经过必定的变换函数将图像的灰度值进行转换,生成新的图像的过程。点运算是图像处理中的基础技术,常见的包括灰度化处理、灰度线性变换、灰度非线性变换、阈值化处理等。编程

一.图像点运算的概述

图像点运算(Point Operation)指对于一幅输入图像,将产生一幅输出图像,输出图像的每一个像素点的灰度值由输入像素点决定。点运算其实是灰度到灰度的映射过程,经过映射变换来达到加强或者减弱图像的灰度。还能够对图像进行求灰度直方图、线性变换、非线性变换以及图像骨架的提取。它与相邻的像素之间没有运算关系,是一种简单和有效的图像处理方法。数组

它在实际中有不少的应用:安全

  • 光度学标定(Photometric Calibration):但愿数字图像的灰度可以真实反映图像的物理特性。好比:去掉非线性、变换灰度的单位。
  • 对比度加强(Contrast Enhancement)或对比度扩展(Contrast stretching):将感兴趣特征的对比度扩展,让其占据灰度级的更大部分。
  • 显示标定(Display Calibration):显示设备不能线性地将灰度值转化为光强度。所以点运算和显示非线性结合,以保持显示图像时的线性关系。
  • 轮廓线肯定:用点运算的方式进行阈值化。

设输入图像为A(x,y),输出图像为B(x,y),则点运算能够表示为:网络

B ( x , y ) = f [ A ( x , y ) ] B(x,y) = f[A(x,y)] B(x,y)=f[A(x,y)]函数

从中能够看出:学习

  • 与几何运算的差异,不会改变图像内像素点之间的空间位置关系。
  • 与局部(领域)运算的差异,输入像素-输出像素一一对应。
  • 又称为对比度加强、对比度拉伸或灰度变换。

图像的灰度变换能够经过有选择的突出图像感兴趣的特征或者抑制图像中不须要的特征,从而改善图像的质量,凸显图像的细节,提升图像的对比度。它也能有效地改变图像的直方图分布,使图像的像素值分布更为均匀。


二.图像灰度化处理

图像灰度化是将一幅彩色图像转换为灰度化图像的过程。彩色图像一般包括R、G、B三个份量,分别显示出红绿蓝等各类颜色,灰度化就是使彩色图像的R、G、B三个份量相等的过程。灰度图像中每一个像素仅具备一种样本颜色,其灰度是位于黑色与白色之间的多级色彩深度,灰度值大的像素点比较亮,反之比较暗,像素值最大为255(表示白色),像素值最小为0(表示黑色)。

假设某点的颜色由RGB(R,G,B)组成,常见灰度处理算法如表1所示:

在这里插入图片描述

表1中Gray表示灰度处理以后的颜色,而后将原始RGB(R,G,B)颜色均匀地替换成新颜色RGB(Gray,Gray,Gray),从而将彩色图片转化为灰度图像。一种常见的方法是将RGB三个份量求和再取平均值,但更为准确的方法是设置不一样的权重,将RGB份量按不一样的比例进行灰度划分。好比人类的眼睛感官蓝色的敏感度最低,敏感最高的是绿色,所以将RGB按照0.29九、0.58七、0.144比例加权平均能获得较合理的灰度图像,如公式2所示。

在这里插入图片描述

1.基于OpenCV的图像灰度化处理

在平常生活中,咱们看到的大多数彩色图像都是RGB类型,可是在图像处理过程当中,经常须要用到灰度图像、二值图像、HSV、HSI等颜色,OpenCV提供了cvtColor()函数实现这些功能。其函数原型以下所示:

  • dst = cv2.cvtColor(src, code[, dst[, dstCn]])
    – src表示输入图像,须要进行颜色空间变换的原图像
    – dst表示输出图像,其大小和深度与src一致
    – code表示转换的代码或标识
    – dstCn表示目标图像通道数,其值为0时,则有src和code决定



该函数的做用是将一个图像从一个颜色空间转换到另外一个颜色空间,其中,RGB是指Red、Green和Blue,一副图像由这三个通道(channel)构成;Gray表示只有灰度值一个通道;HSV包含Hue(色调)、Saturation(饱和度)和Value(亮度)三个通道。在OpenCV中,常见的颜色空间转换标识包括CV_BGR2BGRA、CV_RGB2GRAY、CV_GRAY2RGB、CV_BGR2HSV、CV_BGR2XYZ、CV_BGR2HLS等。下面是调用cvtColor()函数将图像进行灰度化处理的代码。

# -*- coding: utf-8 -*-
# By:Eastmount CSDN 2020-11-12
#encoding:utf-8
import cv2  
import numpy as np  

#读取原始图片
src = cv2.imread('miao.png')

#图像灰度化处理
grayImage = cv2.cvtColor(src,cv2.COLOR_BGR2GRAY)

#显示图像
cv2.imshow("src", src)
cv2.imshow("result", grayImage)

#等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()

输出结果如图1所示,左边是彩色的苗族服饰原图,右边是将彩色图像进行灰度化处理以后的灰度图。其中,灰度图将一个像素点的三个颜色变量设置为至关,R=G=B,此时该值称为灰度值。

在这里插入图片描述

一样,能够调用 grayImage = cv2.cvtColor(src, cv2.COLOR_BGR2HSV) 核心代码将彩色图像转换为HSV颜色空间,如图2所示。

在这里插入图片描述

下面代码对比了九种常见的颜色空间,包括BGR、RGB、GRAY、HSV、YCrCb、HLS、XYZ、LAB和YUV,并循环显示处理后的图像。

#encoding:utf-8
#By:Eastmount CSDN 2020-11-12
import cv2  
import numpy as np  
import matplotlib.pyplot as plt

#读取原始图像
img_BGR = cv2.imread('miao.png')

#BGR转换为RGB
img_RGB = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2RGB)

#灰度化处理
img_GRAY = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2GRAY)

#BGR转HSV
img_HSV = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2HSV)

#BGR转YCrCb
img_YCrCb = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2YCrCb)

#BGR转HLS
img_HLS = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2HLS)

#BGR转XYZ
img_XYZ = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2XYZ)

#BGR转LAB
img_LAB = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2LAB)

#BGR转YUV
img_YUV = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2YUV)

#调用matplotlib显示处理结果
titles = ['BGR', 'RGB', 'GRAY', 'HSV', 'YCrCb', 'HLS', 'XYZ', 'LAB', 'YUV']  
images = [img_BGR, img_RGB, img_GRAY, img_HSV, img_YCrCb,
          img_HLS, img_XYZ, img_LAB, img_YUV]  
for i in range(9):  
   plt.subplot(3, 3, i+1), plt.imshow(images[i], 'gray')  
   plt.title(titles[i])  
   plt.xticks([]),plt.yticks([])  
plt.show()

其运行结果如图3所示,它是图像九种颜色空间相互转换。

在这里插入图片描述


2.基于像素操做的图像灰度化处理

前面讲述了调用OpenCV中cvtColor()函数实现图像灰度化的处理,接下来说解基于像素操做的图像灰度化处理方法,主要是最大值灰度处理、平均灰度处理和加权平均灰度处理方法。

(1)最大值灰度处理方法
该方法的灰度值等于彩色图像R、G、B三个份量中的最大值,公式以下:

在这里插入图片描述

其方法灰度化处理后的灰度图亮度很高,实现代码以下。

# -*- coding: utf-8 -*-
#By:Eastmount CSDN 2020-11-12
#encoding:utf-8
#By:Eastmount CSDN 2020-11-12
import cv2  
import numpy as np  
import matplotlib.pyplot as plt

#读取原始图像
img = cv2.imread('miao.png')

#获取图像高度和宽度
height = img.shape[0]
width = img.shape[1]

#建立一幅图像
grayimg = np.zeros((height, width, 3), np.uint8)

#图像最大值灰度处理
for i in range(height):
    for j in range(width):
        #获取图像R G B最大值
        gray = max(img[i,j][0], img[i,j][1], img[i,j][2])
        #灰度图像素赋值 gray=max(R,G,B)
        grayimg[i,j] = np.uint8(gray)

#显示图像
cv2.imshow("src", img)
cv2.imshow("gray", grayimg)

#等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()

图像最大值灰度处理方法效果输出结果如图4所示,其处理效果的灰度偏亮。

在这里插入图片描述

(2)平均灰度处理方法
该方法的灰度值等于彩色图像R、G、B三个份量灰度值的求和平均值,其计算公式如公式(4)所示:

在这里插入图片描述

平均灰度处理方法实现代码以下。

#encoding:utf-8
#By:Eastmount CSDN 2020-11-12
import cv2  
import numpy as np  
import matplotlib.pyplot as plt

#读取原始图像
img = cv2.imread('miao.png')

#获取图像高度和宽度
height = img.shape[0]
width = img.shape[1]

#建立一幅图像
grayimg = np.zeros((height, width, 3), np.uint8)
print grayimg

#图像平均灰度处理方法
for i in range(height):
    for j in range(width):
        #灰度值为RGB三个份量的平均值
        gray = (int(img[i,j][0]) + int(img[i,j][1]) + int(img[i,j][2]))  /  3
        grayimg[i,j] = np.uint8(gray)

#显示图像
cv2.imshow("src", img)
cv2.imshow("gray", grayimg)

#等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()

图像平均灰度处理方法效果输出结果如图5所示:

在这里插入图片描述

(3)加权平均灰度处理方法
该方法根据色彩重要性,将三个份量以不一样的权值进行加权平均。因为人眼对绿色的敏感最高,对蓝色敏感最低,所以,按下式对RGB三份量进行加权平均能获得较合理的灰度图像。

在这里插入图片描述

加权平均灰度处理方法实现代码以下所示:

#encoding:utf-8
import cv2  
import numpy as np  
import matplotlib.pyplot as plt

#读取原始图像
img = cv2.imread('miao.png')

#获取图像高度和宽度
height = img.shape[0]
width = img.shape[1]

#建立一幅图像
grayimg = np.zeros((height, width, 3), np.uint8)
print(grayimg)

#图像平均灰度处理方法
for i in range(height):
    for j in range(width):
        #灰度加权平均法
        gray = 0.30 * img[i,j][0] + 0.59 * img[i,j][1] + 0.11 * img[i,j][2]
        grayimg[i,j] = np.uint8(gray)

#显示图像
cv2.imshow("src", img)
cv2.imshow("gray", grayimg)

#等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()

图像加权平均灰度处理方法效果输出结果如图6所示:

在这里插入图片描述


三.图像的灰度线性变换

图像的灰度线性变换是经过创建灰度映射来调整原始图像的灰度,从而改善图像的质量,凸显图像的细节,提升图像的对比度。灰度线性变换的计算公式如(6)所示:

在这里插入图片描述

该公式中DB表示灰度线性变换后的灰度值,DA表示变换前输入图像的灰度值,α和b为线性变换方程f(D)的参数,分别表示斜率和截距。

  • 当α=1,b=0时,保持原始图像
  • 当α=1,b!=0时,图像全部的灰度值上移或下移
  • 当α=-1,b=255时,原始图像的灰度值反转
  • 当α>1时,输出图像的对比度加强
  • 当0<α<1时,输出图像的对比度减少
  • 当α<0时,原始图像暗区域变亮,亮区域变暗,图像求补

如图7所示,显示了图像的灰度线性变换对应的效果图。

在这里插入图片描述

1.图像灰度上移变换

该算法将实现图像灰度值的上移,从而提高图像的亮度,其实现代码以下所示。因为图像的灰度值位于0至255区间以内,因此须要对灰度值进行溢出判断。

D B = D A + 50 D_B=D_A+50 DB=DA+50

#encoding:utf-8
#By:Eastmount CSDN 2020-11-12
import cv2  
import numpy as np  
import matplotlib.pyplot as plt

#读取原始图像
img = cv2.imread('miao.png')

#图像灰度转换
grayImage = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

#获取图像高度和宽度
height = grayImage.shape[0]
width = grayImage.shape[1]

#建立一幅图像
result = np.zeros((height, width, 3), np.uint8)

#图像灰度上移变换 DB=DA+50
for i in range(height):
    for j in range(width):
        
        if (int(grayImage[i,j]+50) > 255):
            gray = 255
        else:
            gray = int(grayImage[i,j]+50)
            
        result[i,j] = np.uint8(gray)

#显示图像
cv2.imshow("Gray Image", grayImage)
cv2.imshow("Result", result)

#等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()

图像灰度值上移变换输出结果如图8所示,图像的全部灰度值上移50,图像变得更白了。注意,纯黑色对应的灰度值为0,纯白色对应的灰度值为255。

在这里插入图片描述


2.图像对比度加强变换

该算法将加强图像的对比度,Python实现代码以下所示:

D B = D A × 1.5 D_B=D_A×1.5 DB=DA×1.5

#encoding:utf-8
#By:Eastmount CSDN 2020-11-12
import cv2  
import numpy as np  
import matplotlib.pyplot as plt

#读取原始图像
img = cv2.imread('miao.png')

#图像灰度转换
grayImage = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

#获取图像高度和宽度
height = grayImage.shape[0]
width = grayImage.shape[1]

#建立一幅图像
result = np.zeros((height, width, 3), np.uint8)

#图像对比度加强变换 DB=DA*1.5
for i in range(height):
    for j in range(width):
        
        if (int(grayImage[i,j]*1.5) > 255):
            gray = 255
        else:
            gray = int(grayImage[i,j]*1.5)
            
        result[i,j] = np.uint8(gray)

#显示图像
cv2.imshow("Gray Image", grayImage)
cv2.imshow("Result", result)

#等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()

图像线性对比度加强输出结果如图9所示,图像的全部灰度值加强1.5倍。

在这里插入图片描述


3.图像对比度减弱变换

该算法将减弱图像的对比度,Python实现代码以下所示:

D B = D A × 0.8 D_B=D_A×0.8 DB=DA×0.8

#encoding:utf-8
#By:Eastmount CSDN 2020-11-12
import cv2  
import numpy as np  
import matplotlib.pyplot as plt

#读取原始图像
img = cv2.imread('miao.png')

#图像灰度转换
grayImage = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

#获取图像高度和宽度
height = grayImage.shape[0]
width = grayImage.shape[1]

#建立一幅图像
result = np.zeros((height, width, 3), np.uint8)

#图像对比度减弱变换 DB=DA*0.8
for i in range(height):
    for j in range(width):
        gray = int(grayImage[i,j]*0.8)
        result[i,j] = np.uint8(gray)

#显示图像
cv2.imshow("Gray Image", grayImage)
cv2.imshow("Result", result)

#等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()

其输出结果如图10所示,图像的全部灰度值减弱,图像变得更暗。

在这里插入图片描述


4.图像灰度反色变换

反色变换又称为线性灰度求补变换,它是对原图像的像素值进行反转,即黑色变为白色,白色变为黑色的过程。其Python实现代码以下所示:

D B = 255 − D A D_B=255-D_A DB=255DA

#encoding:utf-8
import cv2  
import numpy as np  
import matplotlib.pyplot as plt

#读取原始图像
img = cv2.imread('miao.png')

#图像灰度转换
grayImage = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

#获取图像高度和宽度
height = grayImage.shape[0]
width = grayImage.shape[1]

#建立一幅图像
result = np.zeros((height, width), np.uint8)

#图像灰度反色变换 DB=255-DA
for i in range(height):
    for j in range(width):
        gray = 255 - grayImage[i,j]
        result[i,j] = np.uint8(gray)

#显示图像
cv2.imshow("Gray Image", grayImage)
cv2.imshow("Result", result)

#等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()

图像灰度反色变换输出结果如图11所示,图像处理先后的灰度值是互补的。

在这里插入图片描述

图像灰度反色变换在医学图像处理中有必定的应用,如图12所示:

在这里插入图片描述


四.图像的灰度非线性变换

图像的灰度非线性变换主要包括对数变换、幂次变换、指数变换、分段函数变换,经过非线性关系对图像进行灰度处理,下面主要讲解三种常见类型的灰度非线性变换。

1.图像灰度非线性变换:

原始图像的灰度值按照DB=DA×DA/255的公式进行非线性变换,其代码以下:

D B = D A × D A / 255 D_B=D_A×D_A/255 DB=DA×DA/255

#encoding:utf-8
#By:Eastmount CSDN 2020-11-12
import cv2  
import numpy as np  
import matplotlib.pyplot as plt

#读取原始图像
img = cv2.imread('miao.png')

#图像灰度转换
grayImage = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

#获取图像高度和宽度
height = grayImage.shape[0]
width = grayImage.shape[1]

#建立一幅图像
result = np.zeros((height, width), np.uint8)

#图像灰度非线性变换:DB=DA×DA/255
for i in range(height):
    for j in range(width):
        gray = int(grayImage[i,j])*int(grayImage[i,j]) / 255
        result[i,j] = np.uint8(gray)

#显示图像
cv2.imshow("Gray Image", grayImage)
cv2.imshow("Result", result)

#等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()

图像灰度非线性变换的输出结果如图13所示:

在这里插入图片描述


2.图像灰度对数变换

图像灰度的对数变换通常表示如公式(7)所示:

在这里插入图片描述

其中c为尺度比较常数,DA为原始图像灰度值,DB为变换后的目标灰度值。图像灰度对数变换如图14所示,它表示对数曲线下的灰度值变化状况,其中x表示原始图像的灰度值,y表示对数变换以后的目标灰度值。

在这里插入图片描述

因为对数曲线在像素值较低的区域斜率大,在像素值较高的区域斜率较小,因此图像通过对数变换后,较暗区域的对比度将有所提高。这种变换可用于加强图像的暗部细节,从而用来扩展被压缩的高值图像中的较暗像素。

对数变换实现了扩展低灰度值而压缩高灰度值的效果,被普遍地应用于频谱图像的显示中。一个典型的应用是傅立叶频谱,其动态范围可能宽达0~106直接显示频谱时,图像显示设备的动态范围每每不能知足要求,从而丢失大量的暗部细节;而在使用对数变换以后,图像的动态范围被合理地非线性压缩,从而能够清晰地显示。

在这里插入图片描述

在图15中,未经变换的频谱通过对数变换后,增长了低灰度区域的对比度,从而加强暗部的细节。下面的代码实现了图像灰度的对数变换。

# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
import cv2

#绘制曲线
def log_plot(c):
    x = np.arange(0, 256, 0.01)
    y = c * np.log(1 + x)
    plt.plot(x, y, 'r', linewidth=1)
    plt.rcParams['font.sans-serif']=['SimHei'] #正常显示中文标签
    plt.title(u'对数变换函数')
    plt.xlim(0, 255), plt.ylim(0, 255)
    plt.show()

#对数变换
def log(c, img):
    output = c * np.log(1.0 + img)
    output = np.uint8(output + 0.5)
    return output

#读取原始图像
img = cv2.imread('2016-.png')

#绘制对数变换曲线
log_plot(42)

#图像灰度对数变换
output = log(42, img)

#显示图像
cv2.imshow('Input', img)
cv2.imshow('Output', output)
cv2.waitKey(0)
cv2.destroyAllWindows()

图16表示通过对数函数处理后的效果图,对数变换对于总体对比度偏低而且灰度值偏低的图像加强效果较好。

在这里插入图片描述

对应的对数函数曲线如图17所示,其中x表示原始图像的灰度值,y表示对数变换以后的目标灰度值。

在这里插入图片描述


3.图像灰度伽玛变换

伽玛变换又称为指数变换或幂次变换,是另外一种经常使用的灰度非线性变换。图像灰度的伽玛变换通常表示如公式(8)所示:

在这里插入图片描述

  • 当γ>1时,会拉伸图像中灰度级较高的区域,压缩灰度级较低的部分。
  • 当γ<1时,会拉伸图像中灰度级较低的区域,压缩灰度级较高的部分。
  • 当γ=1时,该灰度变换是线性的,此时经过线性方式改变原图像。

Python实现图像灰度的伽玛变换代码以下,主要调用幂函数实现。

#encoding:utf-8
import numpy as np
import matplotlib.pyplot as plt
import cv2

#绘制曲线
def gamma_plot(c, v):
    x = np.arange(0, 256, 0.01)
    y = c*x**v
    plt.plot(x, y, 'r', linewidth=1)
    plt.rcParams['font.sans-serif']=['SimHei'] #正常显示中文标签
    plt.title('伽马变换函数')
    plt.xlim([0, 255]), plt.ylim([0, 255])
    plt.show()

#伽玛变换
def gamma(img, c, v):
    lut = np.zeros(256, dtype=np.float32)
    for i in range(256):
        lut[i] = c * i ** v
    output_img = cv2.LUT(img, lut) #像素灰度值的映射
    output_img = np.uint8(output_img+0.5)  
    return output_img

#读取原始图像
img = cv2.imread('2019.png')

#绘制伽玛变换曲线
gamma_plot(0.00000005, 4.0)

#图像灰度伽玛变换
output = gamma(img, 0.00000005, 4.0)

#显示图像
cv2.imshow('Imput', img)
cv2.imshow('Output', output)
cv2.waitKey(0)
cv2.destroyAllWindows()

图18表示通过伽玛变换处理后的效果图,伽马变换对于图像对比度偏低,而且总体亮度值偏高(或因为相机过曝)状况下的图像加强效果明显。

在这里插入图片描述

对应的伽马变换曲线如图19所示,其中x表示原始图像的灰度值,y表示伽马变换以后的目标灰度值。

在这里插入图片描述


五.图像阈值化处理

图像阈值化(Binarization)旨在剔除掉图像中一些低于或高于必定值的像素,从而提取图像中的物体,将图像的背景和噪声区分开来。图像阈值化能够理解为一个简单的图像分割操做,阈值又称为临界值,它的目的是肯定出一个范围,而后这个范围内的像素点使用同一种方法处理,而阈值以外的部分则使用另外一种处理方法或保持原样。

灰度化处理后的图像中,每一个像素都只有一个灰度值,其大小表示明暗程度。阈值化处理能够将图像中的像素划分为两类颜色,常见的阈值化算法如公式(9)所示:

在这里插入图片描述

当某个像素点的灰度Gray(i,j)小于阈值T时,其像素设置为0,表示黑色;当灰度Gray(i,j)大于或等于阈值T时,其像素值为255,表示白色。在Python的OpenCV库中,提供了固定阈值化函数threshold()和自适应阈值化函数adaptiveThreshold(),将一幅图像进行阈值化处理。

1.固定阈值化处理

OpenCV中提供了函数threshold()实现固定阈值化处理,其函数原型以下:

  • dst = cv2.threshold(src, thresh, maxval, type[, dst])
    – src表示输入图像的数组,8位或32位浮点类型的多通道数
    – dst表示输出的阈值化处理后的图像,其类型和通道数与src一致
    – thresh表示阈值
    – maxval表示最大值,当参数阈值类型type选择CV_THRESH_BINARY或CV_THRESH_BINARY_INV时,该参数为阈值类型的最大值
    – type表示阈值类型




其中,图像阈值化处理threshold()函数不一样类型的处理算法如表2所示。

在这里插入图片描述

其对应的阈值化描述如图20所示:

在这里插入图片描述

阈值化处理普遍应用于各行各业,好比生物学中的细胞图分割、交通领域的车牌识别等。经过阈值化处理将所图像转换为黑白两色图,从而为后续的图像识别和图像分割提供更好的支撑做用。下面详细讲解五种阈值化处理算法。

1.二进制阈值化
该函数的原型为threshold(Gray,127,255,cv2.THRESH_BINARY)。其方法首先要选定一个特定的阈值量,好比127,再按照以下所示的规则进行阈值化处理。

在这里插入图片描述

当前像素点的灰度值大于thresh阈值时(如127),其像素点的灰度值设定为最大值(如8位灰度值最大为255);不然,像素点的灰度值设置为0。如阈值为127时,像素点的灰度值为163,则阈值化设置为255;像素点的灰度值为82,则阈值化设置为0。二进制阈值化处理的Python代码以下所示:

#encoding:utf-8
#By:Eastmount CSDN 2020-11-12
import cv2  
import numpy as np  

#读取图片
src = cv2.imread('miao.png')

#灰度图像处理
GrayImage = cv2.cvtColor(src,cv2.COLOR_BGR2GRAY)

#二进制阈值化处理
r, b = cv2.threshold(GrayImage, 127, 255, cv2.THRESH_BINARY)

#显示图像
cv2.imshow("src", src)
cv2.imshow("result", b)

#等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()

输出结果如图21所示,左边是苗族服饰的原图,右边是将原图进行二进制阈值化处理的效果图。像素值大于127的设置为255,小于等于127设置为0。

在这里插入图片描述


2.反二进制阈值化
该函数的原型为threshold(Gray,127,255,cv2.THRESH_BINARY_INV)。其方法首先要选定一个特定的阈值量,好比127,再按照以下所示的规则进行阈值化处理。

在这里插入图片描述

当前像素点的灰度值大于thresh阈值时(如127),其像素点的灰度值设定为0;不然,像素点的灰度值设置为最大值。如阈值为127时,像素点的灰度值为211,则阈值化设置为0;像素点的灰度值为101,则阈值化设置为255。反二进制阈值化处理的Python代码以下所示:

#encoding:utf-8
#By:Eastmount CSDN 2020-11-12
import cv2  
import numpy as np  

#读取图片
src = cv2.imread('miao.png')

#灰度图像处理
grayImage = cv2.cvtColor(src,cv2.COLOR_BGR2GRAY)

#反二进制阈值化处理
r, b = cv2.threshold(grayImage, 127, 255, cv2.THRESH_BINARY_INV)

#显示图像
cv2.imshow("src", src)
cv2.imshow("result", b)

#等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()

图像反二进制阈值化处理输出结果如图22所示:

在这里插入图片描述


3.截断阈值化
该函数的原型为threshold(Gray,127,255,cv2.THRESH_TRUNC)。图像中大于该阈值的像素点被设定为该阈值,小于或等于该阈值的保持不变,好比127。新的阈值产生规则以下:

在这里插入图片描述

好比阈值为127时,像素点的灰度值为167,则阈值化设置为127;像素点的灰度值为82,则阈值化设置为82。截断阈值化处理的Python代码以下所示:

#encoding:utf-8
#By:Eastmount CSDN 2020-11-12
import cv2  
import numpy as np  

#读取图片
src = cv2.imread('miao.png')

#灰度图像处理
grayImage = cv2.cvtColor(src,cv2.COLOR_BGR2GRAY)

#截断阈值化处理
r, b = cv2.threshold(grayImage, 127, 255, cv2.THRESH_TRUNC)

#显示图像
cv2.imshow("src", src)
cv2.imshow("result", b)

#等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()

输出结果如图23所示,图像通过截断阈值化处理将灰度值处理于0至127之间。

在这里插入图片描述


4.阈值化为0
该函数的原型为threshold(Gray,127,255,cv2.THRESH_TOZERO)。按照以下公式对图像的灰度值进行处理。

在这里插入图片描述

当前像素点的灰度值大于thresh阈值时(如127),其像素点的灰度值保持不变;不然,像素点的灰度值设置为0。如阈值为127时,像素点的灰度值为211,则阈值化设置为211;像素点的灰度值为101,则阈值化设置为0。图像阈值化为0处理的Python代码以下所示:

#encoding:utf-8
#By:Eastmount CSDN 2020-11-12
import cv2  
import numpy as np  

#读取图片
src = cv2.imread('miao.png')

#灰度图像处理
grayImage = cv2.cvtColor(src,cv2.COLOR_BGR2GRAY)

#阈值化为0处理
r, b = cv2.threshold(grayImage, 127, 255, cv2.THRESH_TOZERO)

#显示图像
cv2.imshow("src", src)
cv2.imshow("result", b)

#等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()

输出结果如图24所示,该算法把比较亮的部分不变,比较暗的部分处理为0。

在这里插入图片描述


5.反阈值化为0
该函数的原型为threshold(Gray,127,255, cv2.THRESH_TOZERO_INV)。按照以下公式对图像的灰度值进行处理。

在这里插入图片描述

当前像素点的灰度值大于thresh阈值时(如127),其像素点的灰度值设置为0;不然,像素点的灰度值保持不变。如阈值为127时,像素点的灰度值为211,则阈值化设置为0;像素点的灰度值为101,则阈值化设置为101。图像反阈值化为0处理的Python代码以下所示:

#encoding:utf-8
#By:Eastmount CSDN 2020-11-12
import cv2  
import numpy as np  

#读取图片
src = cv2.imread('miao.png')

#灰度图像处理
GrayImage = cv2.cvtColor(src,cv2.COLOR_BGR2GRAY)

#二进制阈值化处理
r, b = cv2.threshold(GrayImage, 127, 255, cv2.THRESH_TOZERO_INV)

#显示图像
cv2.imshow("src", src)
cv2.imshow("result", b)

#等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()

输出结果如图25所示:

在这里插入图片描述

下面文件是五种固定阈值化处理的对比结果。

#encoding:utf-8
#By:Eastmount CSDN 2020-11-12
import cv2  
import numpy as np  
import matplotlib.pyplot as plt

#读取图像
img=cv2.imread('miao.png')
grayImage=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)  

#阈值化处理
ret,thresh1=cv2.threshold(grayImage,127,255,cv2.THRESH_BINARY)  
ret,thresh2=cv2.threshold(grayImage,127,255,cv2.THRESH_BINARY_INV)  
ret,thresh3=cv2.threshold(grayImage,127,255,cv2.THRESH_TRUNC)  
ret,thresh4=cv2.threshold(grayImage,127,255,cv2.THRESH_TOZERO)  
ret,thresh5=cv2.threshold(grayImage,127,255,cv2.THRESH_TOZERO_INV)

#显示结果
titles = ['Gray Image','BINARY','BINARY_INV','TRUNC','TOZERO','TOZERO_INV']  
images = [grayImage, thresh1, thresh2, thresh3, thresh4, thresh5]  
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()

图像固定阈值化处理对比输出结果如图26所示:

在这里插入图片描述


2.自适应阈值化处理

前面讲解的是固定值阈值化处理方法,而当同一幅图像上的不一样部分具备不一样亮度时,上述方法就不在适用。此时须要采用自适应阈值化处理方法,根据图像上的每个小区域,计算与其对应的阈值,从而使得同一幅图像上的不一样区域采用不一样的阈值,在亮度不一样的状况下获得更好的结果。

自适应阈值化处理在OpenCV中调用cv2.adaptiveThreshold()函数实现,其原型以下所示:

  • dst = adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C[, dst])
    – src表示输入图像
    – dst表示输出的阈值化处理后的图像,其类型和尺寸需与src一致
    – maxValue表示给像素赋的知足条件的最大值
    – adaptiveMethod表示要适用的自适应阈值算法,常见取值包括ADAPTIVE_THRESH_MEAN_C(阈值取邻域的平均值) 或 ADAPTIVE_THRESH_GAUSSIAN_C(阈值取自邻域的加权和平均值,权重分布为一个高斯函数分布)
    – thresholdType表示阈值类型,取值必须为THRESH_BINARY或THRESH_BINARY_INV
    – blockSize表示计算阈值的像素邻域大小,取值为三、五、7等
    – C表示一个常数,阈值等于平均值或者加权平均值减去这个常数






当阈值类型thresholdType为THRESH_BINARY时,其灰度图像转换为阈值化图像的计算公式以下所示:

在这里插入图片描述

当阈值类型thresholdType为THRESH_BINARY_INV时,其灰度图像转换为阈值化图像的计算公式以下所示:

在这里插入图片描述

其中,dst(x,y)表示阈值化处理后的灰度值,T(x,y)表示计算每一个单独像素的阈值,其取值以下:

  • 当adaptiveMethod参数采用ADAPTIVE_THRESH_MEAN_C时,阈值T(x,y)为blockSize×blockSize邻域内(x,y)减去参数C的平均值。
  • 当adaptiveMethod参数采用ADAPTIVE_THRESH_GAUSSIAN_C时,阈值T(x,y)为blockSize×blockSize邻域内(x,y)减去参数C与高斯窗交叉相关的加权总和。

下面的代码是对比固定值阈值化与自适应阈值化处理的方法。

# -*- coding: utf-8 -*-
#By:Eastmount CSDN 2020-11-12
import cv2  
import numpy as np  
import matplotlib.pyplot as plt
import matplotlib

#读取图像
img = cv2.imread('miao.png')

#图像灰度化处理
grayImage = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  

#固定值阈值化处理
r, thresh1 = cv2.threshold(grayImage, 127, 255, cv2.THRESH_BINARY)  

#自适应阈值化处理 方法一
thresh2 = cv2.adaptiveThreshold(grayImage, 255, 
cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2)

#自适应阈值化处理 方法二
thresh3 = cv2.adaptiveThreshold(grayImage, 255, 
cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)

#设置字体
matplotlib.rcParams['font.sans-serif']=['SimHei']

#显示图像
titles = ['灰度图像', '全局阈值', '自适应平均阈值', '自适应高斯阈值']
#显示图像
titles = ['Gray Image',
          'Global Thresholding',
          'Adaptive Mean Thresholding',
          'Adaptive Gaussian Thresholding']
images = [grayImage, 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()

输出结果如图27所示,左上角为灰度化处理图像;右上角为固定值全局阈值化处理图像(cv2.threshold);左下角为自适应邻域平均值分割,噪声较多;右下角为自适应邻域加权平均值分割,采用高斯函数分布,其效果相对较好。

在这里插入图片描述


六.本章小结

本文结合做者以前研究民族服饰及图腾识别案例讲解,主要讲解了图像点运算相关知识,从灰度化处理到灰度线性变换和灰度非线性变换,经过编写Python代码处理像素矩阵实现相关功能;接着讲述了图像阈值化处理,调用OpenCV的threshold()实现固定阈值化处理,调用adaptiveThreshold()函数实现自适应阈值化处理。该文知识为后续的图像处理提供良好的基础。

时光嘀嗒嘀嗒的流失,这是我在CSDN写下的第八篇年终总结,比以往时候来的更早一些。《敏而多思,宁静致远》,仅以此篇记念这风雨兼程的一年,这感恩的一年。列车上只写了一半,这两天完成,思远,思君O(∩_∩)O

在这里插入图片描述

2020年8月18新开的“娜璋AI安全之家”,主要围绕Python大数据分析、网络空间安全、人工智能、Web渗透及攻防技术进行讲解,同时分享CCF、SCI、南核北核论文的算法实现。娜璋之家会更加系统,并重构做者的全部文章,从零讲解Python和安全,写了近十年文章,真心想把本身所学所感所作分享出来,还请各位多多指教,真诚邀请您的关注!谢谢。

在这里插入图片描述

(By:Eastmount 2020-11-13 深夜12点夜于武汉 http://blog.csdn.net/eastmount/ )


参考文献: [1] 冈萨雷斯著,阮秋琦译. 数字图像处理(第3版)[M]. 北京:电子工业出版社,2013. [2] 张铮,王艳平,薛桂香等. 数字图像处理与机器视觉——Visual C++与Matlab实现[M]. 北京:人民邮电出版社,2014. [3] 阮秋琦. 数字图像处理学(第3版)[M]. 北京:电子工业出版社,2008. [4] 毛星云,冷雪飞. OpenCV3编程入门[M]. 北京:电子工业出版社,2015.

相关文章
相关标签/搜索