一、RGB直方图

(1)直方图介绍

数码时代,直方图可以说是无处不在。无论是相机的显示屏,还是后期PS、ACR里的窗口,甚至色阶、曲线的工具之中,都可以看到直方图的身影。



要理解直方图,绕不开“亮度”这个概念。人们把照片的亮度分为0到255共256个数值,数值越大,代表的亮度越高。其中0代表纯黑色的最暗区域,255表示最亮的纯白色,而中间的数字就是不同亮度的灰色。人们还进一步把这些亮度分为了5个区域,分别是黑色,阴影,中间调,高光和白色。



当我们用横轴代表0-255的亮度数值。竖轴代表照片中对应亮度的像素数量,这个函数图像就被称为直方图。直方图中柱子的高度,代表了画面中有多少像素是那个亮度,其实就可以看出来画面中亮度的分布和比例。比如下面一个直方图,波峰是在中间偏左的位置(阴影区域),说明画面中有很多深灰或者深色部分。



上面的这个直方图,准确来说应该叫RGB直方图,因为他是由红、绿、蓝三个通道的直方图叠加后除以3而成的。

(2)opencv实现直方图

void minMaxLoc(InputArray src, CV_OUT double minVal, CV_OUT double maxVal=0, CV_OUT Point* minLoc=0, CV_OUT Point* maxLoc=0, InputArray mask=noArray())**

参数:

  • InputArray类型的src,输入单通道数组(图像)。
  • double*类型的minVal,返回最小值的指针。若无须返回,此值置为NULL。
  • double*类型的maxVal,返回最大值的指针。若无须返回,此值置为NULL。
  • Point*类型的minLoc,返回最小位置的指针(二维情况下)。若无须返回,此值置为NULL。
  • Point*类型的maxLoc,返回最大位置的指针(二维情况下)。若无须返回,此值置为NULL。
  • InputArray类型的mask,用于选择子阵列的可选掩膜。
import cv2
import numpy as np
def ImageHist(image,type):
    color = (255,255,255)
    windowName = 'Gray'
    if type == 31:
        color = (255,0,0)
        windowName = 'B Hist'
    elif type == 32:
        color = (0,255,0)
        windowName = 'G Hist'
    elif type == 33:
        color = (0,0,255)
        windowName = 'R Hist'
    hist = cv2.calcHist([image],[0],None,[256],[0.0,255.0])
    minV,maxV,minL,maxL = cv2.minMaxLoc(hist)
    histImg = np.zeros([256,256,3],np.uint8)
    for h in range(256):
        intenNormal = int(hist[h]*256/maxV)
        cv2.line(histImg,(h,256),(h,256-intenNormal),color)
    cv2.imshow(windowName,histImg)
    return histImg
img = cv2.imread('image0.jpg',1)
channels = cv2.split(img)# RGB - R G B
for i in range(0,3):
    ImageHist(channels[i],31+i)
cv2.waitKey(0)
复制代码

结果:



二、直方图均衡化

均衡化指的是把一个分布 (给定的直方图) 映射 到另一个分布 (一个更宽更统一的强度值分布), 所以强度值分布会在整个范围内展开.



(1)灰度均衡化

cvEqualizeHist ( const CvArr src, CvArr dst )**

参数

  • src 输入的 8-比特 单信道图像
  • dst 输出的图像与输入图像大小与数据类型相同
#灰度 直方图均衡化
import cv2
import numpy as np
img = cv2.imread('cantontower02.jpg',1)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
cv2.imshow('src',gray)
dst = cv2.equalizeHist(gray)
cv2.imshow('dst',dst)
cv2.waitKey(0)
复制代码

结果:



(2)彩色均衡化

#彩色 直方图均衡化
import cv2
import numpy as np
img = cv2.imread('image0.jpg',1)
cv2.imshow('src',img)
(b,g,r) = cv2.split(img)#通道分解
bH = cv2.equalizeHist(b)
gH = cv2.equalizeHist(g)
rH = cv2.equalizeHist(r)
result = cv2.merge((bH,gH,rH))# 通道合成
cv2.imshow('dst',result)
cv2.waitKey(0)
复制代码

结果:



(3)YUV均衡化

#YUV 直方图均衡化
import cv2
import numpy as np
img = cv2.imread('image0.jpg',1)
imgYUV = cv2.cvtColor(img,cv2.COLOR_BGR2YCrCb)
cv2.imshow('src',img)
channelYUV = cv2.split(imgYUV)
# 通道拆分
channelYUV[0] = cv2.equalizeHist(channelYUV[0])
channels = cv2.merge(channelYUV)
# 通道合并
result = cv2.cvtColor(channels,cv2.COLOR_YCrCb2BGR)
cv2.imshow('dst',result)
cv2.waitKey(0)
复制代码

结果:



三、图片内容识别

inpaint( InputArray src, InputArray inpaintMask, OutputArray dst, double inpaintRadius, int flags );

参数

  • InputArray src 表示要修复的图像,
  • InputArray inpaintMask表示修复模板,
  • OutputArray dst 表示修复后的图像,
  • double inpaintRadius 表示修复的半径,
  • int flags 表示修复使用的算法 。 opencv提供了两种选择 CV_INPAINT_TELEA 和 CV_INPAINT_NS。
import cv2 
import numpy as np

img = cv2.imread('cantondamaged.jpg',1)
cv2.imshow('src',img)
# 1、输入要修复的图片

imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
paint = np.zeros((height,width,1),np.uint8)

cv2.rectangle(paint,(50,100),(200,300),(255,0,0),5)
cv2.imshow('paint',paint)
#2、选择修复的区间

imgDst = cv2.inpaint(img,paint,3,cv2.INPAINT_TELEA)
# 3、识别修复

cv2.imshow('image',imgDst)
cv2.waitKey(0)
复制代码

结果:



四、亮度增强

import cv2
import numpy as np
img = cv2.imread('cantontower02.jpg',1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
cv2.imshow('src',img)
dst = np.zeros((height,width,3),np.uint8)
for i in range(0,height):
    for j in range(0,width):
        (b,g,r) = img[i,j]
        bb = int(b)+40
        gg = int(g)+40
        rr = int(r)+40
        # 通过增加GRB来增强亮度
        if bb>255:
            bb = 255
        if gg>255:
            gg = 255
        if rr>255:
            rr = 255
        dst[i,j] = (bb,gg,rr)
cv2.imshow('dst',dst)
cv2.waitKey(0)
复制代码

结果:



五、磨皮美白

双边滤波器(Bilateral filter)是一种可以保边去噪的滤波器。可以滤除图像数据中的噪声,且还会保留住图像的边缘、纹理等(因噪声是高频信号,边缘、纹理也是高频信息,高斯滤波会在滤除噪声的同时使得边缘模糊)。那这么优秀的一个滤波器,他到底是个什么呢,其实,它和我们普通的高斯滤波器一样,也是使用一个卷积核(模板矩阵),叠加到待处理像素点上,使用对应邻域像素点的加权求和来作为新的输出像素点的值一种方法,简单来说,双边滤波和高斯滤波一样,不同只在于模板矩阵的不同。

双边滤波器的模板系数矩阵由高斯模板矩阵点乘(元素级相乘)值域系数获得。可以与其相比较的两个滤波器是:高斯低通滤波器和α-截尾均值滤波器(去掉百分率为α的最小值和最大之后剩下像素的均值作为滤波器)。

双边滤波器中,输出像素的值依赖于邻域像素的值的加权组合,


权重系数w(i,j,k,l)取决于定义域核 和值域核 的乘积

bilateralFilter (InputArray src, OutputArray dst, int d, double sigmaColor, double sigmaSpace, int borderType=BORDER_DEFAULT )

参数

  • InputArray src: 输入图像,可以是Mat类型,图像必须是8位或浮点型单通道、三通道的图像。
  • OutputArray dst: 输出图像,和原图像有相同的尺寸和类型。
  • int d: 表示在过滤过程中每个像素邻域的直径范围。如果这个值是非正数,则函数会从第五个参数sigmaSpace计算该值。
  • double sigmaColor: 颜色空间过滤器的sigma值,这个参数的值越大,表明该像素邻域内有越宽广的颜色会被混合到一起,产生较大的半相等颜色区域。
  • double sigmaSpace: 坐标空间中滤波器的sigma值,如果该值较大,则意味着颜色相近的较远的像素将相互影响,从而使更大的区域中足够相似的颜色获取相同的颜色。当d>0时,d指定了邻域大小且与sigmaSpace五官,否则d正比于sigmaSpace.
  • int borderType=BORDER_DEFAULT: 用于推断图像外部像素的某种边界模式,有默认值BORDER_DEFAULT.
import cv2
img = cv2.imread('woman.png',1)
cv2.imshow('src',img)
dst = cv2.bilateralFilter(img,35,155,90)
cv2.imshow('dst',dst)
cv2.waitKey(0)
复制代码

结果:



六、高斯模糊

GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, int borderType=BORDER_DEFAULT)

参数

  • src,输入图像,即源图像,填Mat类的对象即可。它可以是单独的任意通道数的图片,但需要注意,图片深度应该为CV_8U,CV_16U, CV_16S, CV_32F 以及 CV_64F之一。
  • dst,即目标图像,需要和源图片有一样的尺寸和类型。比如可以用Mat::Clone,以源图片为模板,来初始化得到如假包换的目标图。
  • ksize,高斯内核的大小。其中ksize.width和ksize.height可以不同,但他们都必须为正数和奇数(并不能理解)。或者,它们可以是零的,它们都是由sigma计算而来。
  • sigmaX,表示高斯核函数在X方向的的标准偏差。
  • sigmaY,表示高斯核函数在Y方向的的标准偏差。若sigmaY为零,就将它设为sigmaX,如果sigmaX和sigmaY都是0,那么就由ksize.width和ksize.height计算出来。为了结果的正确性着想,最好是把第三个参数Size,第四个参数sigmaX和第五个参数sigmaY全部指定到。
  • borderType,用于推断图像外部像素的某种边界模式。注意它有默认值BORDER_DEFAULT。
import cv2
import numpy as np
img = cv2.imread('cantontower02.jpg',1)
cv2.imshow('src',img)
dst = cv2.GaussianBlur(img,(5,5),1.5)
cv2.imshow('dst',dst)
cv2.waitKey(0)
复制代码

结果: