opencv学习笔记(3)

本篇的主要内容是关于图像的像素操作(rgb、灰度转换、图像增强、二值化)

3.1 rgb、灰度转换:cvtColor

cv2.cvtColor(img,code)
        #img: 图像对象
        #code:
            cv2.COLOR_RGB2GRAY: RGB转换到灰度模式
            cv2.COLOR_BGR2RGB: 在与matlibplot用到,由于cv2.imread读取的是bgr,使用matlibplot.imshow时需要进行转换
            cv2.COLOR_RGB2HSV: RGB转换到HSV模式(hue,saturation,Value)

灰度图片转换:

代码:

import cv2

img = cv2.imread(r"C:\Users\LENOVO\Desktop\lena.png")
img_gray = cv2.cvtColor(img,cv2.COLOR_RGB2GRAY)

cv2.imshow("img",img)
cv2.imshow("img_gray",img_gray)
cv2.waitKey(0)
cv2.destroyAllWindows()

结果:

 3.2灰度直方图

灰度直方图是在已转化的灰度图像上,统计每一个灰度值的频数而得出的直方图。其横坐标通常表示0-255的灰度值,而纵坐标表示它们出现的频数。绘制灰度直方图可以通过cv2.calcHist()进行统计,然后使用plt.hist进行绘制。

cv2.calcHist(img,channels,mask,histSize,ranges)  
        img:输入图像,为列表,如[img]
        channels: 计算的通道,为列表,如[0]表示单通道,[0,1]统计两个通道
        mask: 掩模,和输入图像大小一样的矩阵,为1的地方会进行统计(与图像逻辑与后再统计);无掩模时为None
        histSize: 每一个channel对应的bins个数,为列表,如[256]表示256个像素值
        ranges: bins的边界,为列表,如[0,256]表示像素值范围在0-256之间

代码如下:

import cv2 
import matplotlib.pyplot as plt
import numpy as np

img = cv2.imread(r"C:\Users\LENOVO\Desktop\lena.png",0)
hist = cv2.calcHist([img],[0],None,[256],[0,256])

plt.subplot(1,2,1),plt.imshow(img),plt.xticks([]),plt.yticks([])
plt.subplot(1,2,2),plt.hist(img.ravel(),bins=256,range=[0,256])
plt.xlim([0,256]),plt.xlabel("gray level"),plt.ylabel("number of pixels")
plt.show()

结果如下:

 同时,也可以通过np.histogram()和plt.hist()获得灰度分布:

对于同一张图,代码如下:

histogram,bins = np.histogram(img,bins=256,range=[0,256])
plt.hist(img.ravel(),bins=256,range=[0,256])
plt.xlabel("gray level")
plt.ylabel("number of pixels")
plt.show()

结果如下:

3.3 像素的线性变换

对每个点上每个通道的像素值进行线性变换,形式为:y=ax+b,可以获得更为明亮的图片。可以通过cv2.convertScaleAbs()实现。

dst = cv2.convertScaleAbs(img,alpha=a,beta=b)
    #img: 图像对象矩阵
  #dst:输出图像矩阵
    #a:y=ax+b中的a值
    #b:y=ax+b中的b值
    #(对于计算后大于255的像素值会截断为255)

代码如下:

import cv2 
import matplotlib.pyplot as plt

img = cv2.imread(r"C:\Users\LENOVO\Desktop\lena.png")

img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
img_bright = cv2.convertScaleAbs(img,alpha=1.5,beta=0)

plt.subplot(1,2,1),plt.imshow(img),plt.xticks([]),plt.yticks([])
plt.subplot(1,2,2),plt.imshow(img_bright),plt.xticks([]),plt.yticks([])
plt.show()

结果如下:

 3.4 归一化(正规化)

对于上述线性变换,系数a,b需要自己摸索设置。直方图正规化的系数固定,一般将原图片的像素值范围映射到[0,255]范围内。假设原图片的像素值分布范围为Input:[min, max], 映射后的范围为Output:[0,255], 则对应的系数a=(255-0)/(max-min),  系数b=0。即计算公式:

 cv2.normalize可以实现上述操作:

cv2.normalize(src,dst,alpha,beta,normType,dtype,mask)
        #src: 图像对象矩阵
        #dst:输出图像矩阵(和src的shape一样)
        #alpha:正规化的值,如果是范围值,为范围的下限 (alpha – norm value to normalize to or the lower range boundary in case of the range normalization.)
        #beta:如果是范围值,为范围的上限;正规化中不用到 ( upper range boundary in case of the range normalization; it is not used for the norm normalization.)
        #norm_type:normalize的类型
                    cv2.NORM_L1:归一化数组的(曼哈顿距离)L1-范数(绝对值的和)
                    cv2.NORM_L2:归一化数组的(欧几里德距离)L2-范数
                    cv2.NORM_MINMAX:线性归一化
                    cv2.NORM_INF: 归一化数组的(切比雪夫距离)L∞范数(绝对值的最大值)
                    
        #dtype: 输出图像矩阵的数据类型,默认为-1,即和src一样
        #mask:掩模矩阵,只对感兴趣的地方归一化

 四种类型:

 

 

代码如下:

import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np

img = cv2.imread(r"C:\Users\LENOVO\Desktop\lena.png")
img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
img_norm = cv2.normalize(img,dst=None,alpha=350,beta=10,norm_type=cv2.NORM_MINMAX)

plt.subplot(1,2,1),plt.imshow(img),plt.xticks([]),plt.yticks([])
plt.subplot(1,2,2),plt.imshow(img_norm),plt.xticks([]),plt.yticks([])
plt.show()

结果如下:

 3.5 伽马变换

在图像处理中,常用伽马变换来处理图像过曝或曝光不足的问题,即通过非线性变换的方式,使得图片中过暗的区域增强,让过亮的区域的灰度值降低。

原理如下:

 

 其中,r代表输入,取值范围为[0,1]。s为经过伽马变换后的灰度输出值。c为灰度缩放系数,通常取1。γ为伽马因子大小,控制了整个变换的缩放程度。(具体请参考:伽马变换原理及示例_opencv_fjc的博客-CSDN博客_伽马变换

该变换主要用np实现,代码如下:

import matplotlib.pyplot as plt
import numpy as np

img = cv2.imread(r"C:\Users\LENOVO\Desktop\lena.png")
img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
img_norm = img/255.0  #注意255.0得采用浮点数
img_gamma = np.power(img_norm,0.4)*255.0
img_gamma = img_gamma.astype(np.uint8)

plt.subplot(1,2,1),plt.imshow(img),plt.xticks([]),plt.yticks([])
plt.subplot(1,2,2),plt.imshow(img_gamma),plt.xticks([]),plt.yticks([])
plt.show()

结果如下:

 3.6 全局直方图均衡化

直方图均衡化的目的是将原图片每个像素值的像素点个数进行重新分配到[0,255]的256个像素值上,使得每个像素值对应的像素点个数近似相等,即重新分配后,0-255的每个像素值对应的像素点个数近似为(rows*cols/256),(直方图均衡化对应的数学原理参考:直方图均衡化的数学原理_ncf的博客-CSDN博客)。opencv里面equalizeHist()函数实现了相应的功能,只能处理单通道数据,参数列表如下:

dst = cv2.equalizeHist(img)
        #img: 图像对象矩阵,必须为单通道的uint8类型的矩阵数据
        #dst: 输出图像矩阵(和src的shape一样)

代码如下:

import cv2 as cv
import matplotlib.pyplot as plt

img = cv2.imread(r"C:\Users\LENOVO\Desktop\lena.png",0)
img_equal = cv2.equalizeHist(img)

plt.subplot(1,2,1),plt.imshow(img),plt.xticks([]),plt.yticks([])
plt.subplot(1,2,2),plt.imshow(img_equal),plt.xticks([]),plt.yticks([])
plt.show()

结果如下:

 3.7 限制对比度的自适应直方图均衡化

在某些图片中,可能会因为光照不均匀、噪声等缘故导致某些距离较远的区域的灰度差异过于悬殊,影响很大,需要通过限制对比度来进行抑制,即限制对比度自适应直方图均衡化。相比全局直方图均衡化,自适应直方图均衡化将图像划分为不重叠的小块,在每一小块进行直方图均衡化。

opencv通过createCLAHE()和apply()函数来实现,其对应参数如下:

clahe=cv2.createCLAHE(clipLimit,tileGridSize)
        #clipLimit:限制对比度的阈值,默认为40,直方图中像素值出现次数大于该阈值,多余的次数会被重新分配
        #tileGridSize:图像会被划分的大小, 如tileGridSize=(8,8),默认为(8,8)
    
calhe.apply(img) 
        #对img进行限制对比度自适应直方图均衡化

代码如下:

import cv2
import matplotlib.pyplot as plt
import math

img = cv2.imread(r"C:\Users\LENOVO\Desktop\lena.png",0)
clahe = cv.createCLAHE(3,(8,8))
dst = clahe.apply(img)

plt.subplot(1,2,1),plt.imshow(img),plt.xticks([]),plt.yticks([])
plt.subplot(1,2,2),plt.imshow(dst),plt.xticks([]),plt.yticks([])
plt.show()

结果如下:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值