飞道的博客

小白入门计算机视觉(二) : 图像基本处理----灰度图和二值化

429人阅读  评论(0)


从本节开始,我就要正式踏上小白的计算机视觉探索之路,先从图像基础学习吧

解剖图像

要学会图像处理首先就得知道图像的结构,平时我们见到的图片有彩色的,也有黑白的,还有灰色图,尤其是手机里的美图工具,有很多图片效果可以供我们选择,图片的存储大小也可以自己自定义去更改,我们先探索一下图像的构造

像素

像素是分辨率的单位,也是构成位图图像的基本单元,并且每个像素都有自己的颜色,所以才能看到色彩不一,清晰度不同的图片

分辨率

分辨率也可以称作是解析度,就是单位英寸内的像素点数,单位为PPI(Pixels Per Inch)。但是在平时分辨率总被我们错误的认为就是位图图像内的像素点数量

色调

各种图像色彩模式下原色的明暗程度,级别范围从0到255,共256级色调,这也是图像为什么能展示出不同的颜色。
我们常见的彩色图像有两种类型:RGB(光学原色)和CMYK(色彩原色)。RGB表示的是:红,蓝,绿,,主要用于相机,视频等;CMYK表示的是:青,品红,黄,黑,主要用于印刷行业

图像视觉指标

对比度:指不同颜色之间的差别。对比度=最大灰度值/最小灰度值
亮度:这个容易理解,就是让图像色彩更加鲜亮
锐度:即清晰度,它是反映图像平面清晰度和图像边缘锐利程度的一个指标
色度:色彩的纯度,也叫饱和度或彩度

图像处理基本原理

RGB模型


RGB色彩模式是工业界的一种颜色标准,这个标准几乎包括了人类实例所能感知的所有颜色。通过上面这张图就可以看出当三个原色都不覆盖的区域,就呈现出黑色,当三个原色叠加起来中心最亮的叠区为白色的,所以在图像处理过程中[0,0,0]表示的是黑色,[255,255,255]表示的是白色。
RGB的每个通道都有0-255共256级色彩,按这样计算,整个RGB模型可以组合出256x256x256=16777216中色彩,通常也称1600万色或者24位色(2的24次方)。说到这里还有一种ARGB模型,也就是色彩模式加上Alpha(透明度)通道,常见于32位位图的存储结构。
RGB模型的元神其实就是三维直角坐标系中的一个单位立方体(图中的每个点显示的是RGB值不是坐标),在正方体的主对角线上的RGB分量都相等,就会产生由暗到亮的黑白图像,这便是灰度。(0,0,0)是黑色,对应的RGB就是[0,0,0],(1,1,1)是白色,对应的RGB就是[255,255,255]

灰度

表示图像像素明暗程度的数值,也就是黑白图像中点的颜色深度。范围一般为0-255。白色为 255,黑色为0。

灰度化作用

处理图像时候为什么要先灰度化呢?主要有两个原因

1. RGB并不能反映图像的形态特征,只是从光学的原理上进行颜色的调配
2.减小图像原始数据量,便于后续处理时计算量更少

灰度化的方法

常用的图像灰度化有四种算法:分量法,最大值法,均值法,加权均值法

分量法
分量法就是用RGB三个分量的某一个分量作为该点的灰度值
G r a y ( R ) ( i , j ) = R ( i , j ) Gray_{(R)}(i,j)=R(i,j)
G r a y ( G ) ( i , j ) = G ( i , j ) Gray_{(G)}(i,j)=G(i,j)
G r a y ( B ) ( i , j ) = B ( i , j ) Gray_{(B)}(i,j)=B(i,j)
python实现分量法

def gray_RGB_one(img,temp):
    '''
    :param temp: 分量 B:0,G:1,R:2
    :return:
    '''
    # 读取图片
    image = cv2.imread(img)
    size = image.shape
    #这里是要利用numpy创建一个图像,完整代码我会在后面附上
    grayimg = create_img(size[:2],255)
    for i in range(size[0]):
        for j in range(size[1]):
            grayimg[i, j] = image[i,j][temp]
    return grayimg

最大值法
最大值法就是将彩色图像中的三分量亮度的最大值作为灰度图的灰度值
G r a y ( i , j ) = m a x ( R ( i , j ) , G ( i , j ) , B ( i , j ) ) Gray(i,j)=max(R(i,j),G(i,j),B(i,j))
python实现最大值法

def gray_max(img):
    # 读取图片
    image = cv2.imread(img)
    size = image.shape
    grayimg = create_img(size[:2], 255)
    for i in range(size[0]):
        for j in range(size[1]):
            grayimg[i, j] = max(image[i, j][0], image[i, j][1], image[i, j][2])
    return grayimg

均值法
均值法就是将彩色图像中的三分量亮度求平均得到一个灰度图
G r a y ( i , j ) = ( R ( i , j ) + G ( i , j ) + B ( i , j ) ) / 3 Gray(i,j)=(R(i,j)+G(i,j)+B(i,j))/3
python实现均值法

def gray_mean(img):
    # 读取图片
    image = cv2.imread(img)
    size = image.shape
    # print(size[:2])
    grayimg = create_img(size[:2], 255)
    for i in range(size[0]):
        for j in range(size[1]):
            grayimg[i, j] = (image[i, j][0] + image[i, j][1] + image[i, j][2])/3
    return grayimg

加权均值法
加权均值法就是为每个通道加上一个权重,权重之和一定要等于1。
G r a y ( i , j ) = W R R ( i , j ) + W G G ( i , j ) + W B B ( i , j ) Gray(i,j)=W_R*R(i,j)+W_G*G(i,j)+WB*B(i,j)
这里说明一下,一般来说有两组比较常用的权重
G r a y ( i , j ) = 0.072169 B ( i , j ) + 0.715160 G ( i , j ) + 0.212671 R ( i , j ) Gray(i,j)=0.072169*B(i,j)+0.715160*G(i,j)+0.212671*R(i,j)
还有一个是从人体生理学角度所提出的一种权值(人眼对绿色的敏感最高,对蓝色敏感最低)
G r a y ( i , j ) = 0.114 B ( i , j ) + 0.578 G ( i , j ) + 0.299 R ( i , j ) Gray(i,j)=0.114*B(i,j)+0.578*G(i,j)+0.299*R(i,j)
python实现加权均值法

def gray_w_mean(img,W):
    '''
    :param W: W为一个数组[1,2,3],按照BGR的系数传参
    :return: 
    '''
    # 读取图片
    image = cv2.imread(img)
    size = image.shape
    # print(size[:2])
    grayimg = create_img(size[:2], 255)
    for i in range(size[0]):
        for j in range(size[1]):
            grayimg[i, j] = W[0] * image[i, j][0] + W[1] * image[i, j][1] + W[2] * image[i, j][2]
    return grayimg

我们看看处理后的效果吧
完整代码

import cv2
import numpy as np


def create_img(size, imgvalue=255):
    '''
    创建一个单通道的图像
    :param size: 图片大小 (m,n)
    :param imgvalue: 色调值默认255
    :return:
    '''
    # 创建通道图像  灰度图像
    image = np.zeros((size[0], size[1]), np.uint8)
    image[:, :] = np.ones([size[0], size[1]]) * imgvalue
    return image

def gray_RGB_one(img, temp):
    '''
    :param temp: 分量 B:0,G:1,R:2
    :return:
    '''
    # 读取图片
    image = cv2.imread(img)
    size = image.shape
    grayimg = create_img(size[:2], 255)
    for i in range(size[0]):
        for j in range(size[1]):
            grayimg[i, j] = image[i, j][temp]
    return grayimg


def gray_max(img):
    # 读取图片
    image = cv2.imread(img)
    size = image.shape
    grayimg = create_img(size, 255)
    for i in range(size[0]):
        for j in range(size[1]):
            grayimg[i, j] = max(image[i, j][0], image[i, j][1], image[i, j][2])
    return grayimg

def gray_mean(img):
    # 读取图片
    image = cv2.imread(img)
    size = image.shape
    # print(size[:2])
    grayimg = create_img(size[:2], 255)
    for i in range(size[0]):
        for j in range(size[1]):
            grayimg[i, j] = (image[i, j][0] + image[i, j][1] + image[i, j][2])/3
    return grayimg

def gray_w_mean(img,W):
    '''
    :param W: W为一个数组[1,2,3],按照BGR的系数传参
    :return:
    '''
    # 读取图片
    image = cv2.imread(img)
    size = image.shape
    # print(size[:2])
    grayimg = create_img(size[:2], 255)
    for i in range(size[0]):
        for j in range(size[1]):
            grayimg[i, j] = W[0] * image[i, j][0] + W[1] * image[i, j][1] + W[2] * image[i, j][2]
    return grayimg

img = "data.jpg"
W1 = [0.114,0.578,0.299]
W2 = [0.072169,0.715160,0.212671]
img11 = gray_w_mean(img,W1)
img12 = gray_w_mean(img,W2)
img2B = gray_RGB_one(img, 0)
img2G = gray_RGB_one(img, 1)
img2R = gray_RGB_one(img, 2)
img3 = gray_mean(img)
img4 = gray_max(img)
imgs1 = np.hstack((img11,img12,img3,img4))
imgs2 = np.hstack((img2B,img2G,img2R))
cv2.imshow("grayimg",imgs1)
cv2.imshow("grayimg2",imgs2)
cv2.waitKey(0)

我们先看原图

转灰度图后的效果



从最终的效果来看,和原图相比,用加权均值处理的的两个灰度图最清晰

二值化

二值化就是就是将整个图像呈现出明显的黑白效果的过程。
在数字图像处理中,二值图像占有非常重要的地位,图像的二值化使图像中数据量大为减少,从而能凸显出目标的轮廓,增加识别率,比如现在常见的OCR识别技术。

二值化原理

图像二值化是在图像灰度图的基础上按照阈值将256级的灰度图的色调分割为0或者255,也就是图像只有两种颜色,非黑即白。

二值化方法

二值化常用的方法有全局二值化,局部二值化,局部自适应二值化。
全局二值化就是设置一个全局的阈值,对图像进行二值化
局部二值化的方法就是按照一定的规则将整幅图像划分为N个窗口,对这N个窗口中的每一个窗口再按照一个统一的阈值T将该窗口内的像素划分为两部分,进行二值化处理
自适应二值化就是在局部二值化的基础之上,将阈值的设定更加合理化。该方法的阈值是通过对该窗口像素的平均值E,像素之间的差平方P,像素之间的均方根值Q等各种局部特征,设定一个参数方程进行阈值的计算,例如:T=aE+bP+c*Q,其中a,b,c是自由参数。这样得出来的二值化图像就更能表现出二值化图像中的细节
这里我就先介绍一个最简单的全局二值化
要想从多值的图像中直接提取出目标物体,最常用的方法就是设定一个全局的阈值T,用T将图像的数据分成两部分:大于T的像素群和小于T的像素群。将大于T的像素群的像素值设定为白色(或者黑色),小于T的像素群的像素值设定为黑色(或者白色)。
比如:计算每一个像素的(R+G+B)/3,如果大于我们设定的阈值,则设置该像素为白色,即R=G=B=255;否则设置为黑色,即R=G=B=0
为了计算方便,一般情况下我们都是先把图片转成灰度图,再做二值化处理

    for i in range(size[0]):
        for j in range(size[1]):
            print(grayimg[i,j])
            if (grayimg[i,j]< T):
                grayimg[i,j] = 0
            else:
                grayimg[i,j] = 255

二值化中的算法

二值化的算法常见的有膨胀算法、腐蚀算法,而这两种算法的交互使用又形成了开运算和闭运算。这个暂时先了解一下吧,到后面我研究透了再另详细的分析吧

阈值的选取

阈值在二值化处理过程中是一个核心参数,那么阈值的选取也是二值化过程中的核心算法。
一般比较常见的有七种:Otsu(大律法)、最大熵、迭代法、自适应阀值、手动、迭代法、基本全局阈值法,且都已经封装在在opencv里了

    THRESH_BINARY     = 0  #  大于thresh的设为maxval
    THRESH_BINARY_INV = 1  #  大于thresh的设为0
    THRESH_TRUNC      = 2  #  大于thresh的使用threshold函数,小于等于的不处理
    THRESH_TOZERO     = 3  #  大于thresh的不处理,小于等于的设为0
    THRESH_TOZERO_INV = 4  #  大于thresh的设为0,小于等于的不处理
    THRESH_MASK       = 7  #  掩盖,可以理解为马赛克
    THRESH_OTSU       = 8  #  使用OTSU算法计算出阈值
    THRESH_TRIANGLE   = 16 #  使用TRIANGLE算法计算出阈值,与直方图技术法原理类似

我拿一个数字图像做个简单的二值化处理吧

number.jpg
import cv2

def binary_deal(img,T):
    '''
    :param T: 阈值设定
    :return:
    '''
    img = cv2.imread(img)
    grayimg = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    size = grayimg.shape
    for i in range(size[0]):
        for j in range(size[1]):
            if (grayimg[i,j]< T):
                grayimg[i,j] = 0
            else:
                grayimg[i,j] = 255
    return grayimg
img = "number.jpg"
img1 = binary_deal(img,100)
cv2.imshow("binary",img1)
cv2.waitKey(0)

我用opencv先把图片转换成了灰度图,然后通过全局阈值的方法进行二值化处理,废话不多说直接看效果吧

binary.jpg

图像二值化处理的原理和算法我还没研究透,就先分享点基础的吧,随后再简单提一下灰度化时候图像失真的问题吧

图像失真问题

我们在处理图像时候因为采用的是整型的RGB值,这样计算后会丢失掉小数点后面的部分,这样就会导致图像颜色值失真,计算过程越多,失真就越严重。
为了减少图像失真,一般情况下会将RGB值转为[0,1]之间的浮点数。
f l o a t R = R i j 255 float_R=\frac{R_{ij}}{255}
f l o a t G = G i j 255 float_G=\frac{G_{ij}}{255}
f l o a t B = B i j 255 float_B=\frac{B_{ij}}{255}
这样就将RGB值误差的变化量缩小了255倍,在处理时候,图像失真情况也会得到很大的改善


转载:https://blog.csdn.net/LPJCSY/article/details/104984436
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场