图像加强、锐化,利用 Python-OpenCV 来实现 4 种方法!

图像加强目的使得模糊图片变得更加清晰、图片模糊的缘由是由于像素灰度差值变化不大,图片各区域产生视觉效果彷佛都是同样的, 没有较为突出的地方,看起来不清晰的感受web

解决这个问题的最直接简单办法,放大像素灰度值差值、使图像中的细节更加清晰。数组

目前较为经常使用的几个方法:伽马变换、线性变换、分段线性变换、直方图均衡化,对于图像对比度加强,都能取得不错的效果!微信

本文将对每种方法 简单介绍一下,并借助于 Python 、OpenCV 进行代码实现,提早说一下哈,下面处理的图像对象都是单通道灰度图,不是三通道彩色图!函数

1,线性变换

线性变换的原理是对全部像素值乘上一个扩张因子 ,像素值大的变得越大,像素值小的变得越小,从而达到图像加强的效果,这里利用 Numpy 的数组进行操做;
ui

须要注意的是,像素值最大为255,所以在数组相乘以后须要进行数值截断操做,最终代码以下:this

def line_trans_img(img,coffient):
    if len(img.shape) == 3:
        img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    out = 2*img
    #像素截断;;;
    out[out>255] = 255
    out = np.around(out)
    return out

这里 设置为 2 ,变换结果以下,会看到强光处出现失真效果spa

line.png

这里对排列图片作一下说明,从左到右依次为 原图灰度图、原图灰度直方图、处理以后的灰度图、处理以后的灰度直方图,如下的图片排列方式相同.net

2,伽马变换

伽马变换对像素值作的是幂次方变换,主要是图像的灰度级发生改变,转换的原理公式为:

参数  的设定 能够参照下面:3d

Snipaste_2020-05-26_20-18-17.png
  • >1 时,会减少灰度级较高的地方,增大灰度级较低的地方;code

  • <1 时,会增大灰度级较高的地方,减少灰度级较低的地方;

def gama_transfer(img,power1):
    if len(img.shape) == 3:
         img= cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
    img = 255*np.power(img/255,power1)
    img = np.around(img)
    img[img>255] = 255
    out_img = img.astype(np.uint8)
    return out_img

这里 Gamma 分别取 1.5,0.5,结果以下:

gamma1.5.png
gamma0.5.png

结果来看,相对来讲  对图像加强的结果会更好一点

3,分段线性分割

分段线性分割,提早把图像的灰度级分为几部分,而后对每一部分的像素值作不一样的线性变换,像素值基本变换原理:

这里写的代码总感受效率特别慢(逐像素改变),知道改进方法的小伙伴们望告知:

def seg_augment_img(img,start,c1,end,c2,b2,c3,b3):
    if len(img.shape) == 3:
         img= cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

    out_img = np.zeros(img.shape)
    for i in range(img.shape[0]):
        for j in range(img.shape[1]):
            if img[i][j] <start:
                out_img[i][j] = img[i][j]*c1
            elif img[i][j] < end:
                out_img[i][j] = img[i][j] *c2 + b2
            else:
                out_img[i][j] = img[i][j] * c3 +b3

    out_img[out_img>255] = 255
    out = np.around(out_img)
    out = out.astype(np.uint8)
    return out

函数中的参数分别为 50,0.5,150,3.6,-310,0.238,194,结果以下:

seg_line.png

4,直方图均衡化

每一个灰度图像都有本身的灰度直方图,均衡化的原理是,先根据灰度直方图计算累加灰度直方图,根据灰度图与累加灰度图的映射关系关联输入图像与输出图图像的映射关系

映射关系原理以下:

所以,这里几个重要部分:1,计算出灰度直方图;2,计算累加灰度直方图;3,根据 1 和 2 获得映射关系,最终输出灰度像素值;

def get_imghist(img):
    # 判断图像是否为三通道;
    if len(img.shape) == 3:
        img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    # 无 Mask,256个bins,取值范围为[0,255]
    hist = cv2.calcHist([img],[0],None,[256],[0,255])
    return hist


def cal_equalhist(img):
    if len(img.shape) == 3:
         img= cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    h,w = img.shape[:2]
    grathist = get_imghist(img)

    zerosumMoment = np.zeros([256],np.uint32)
    for p in range(256):
        if p ==0:
            zerosumMoment[p] = grathist[0]
        else:
            zerosumMoment[p] = zerosumMoment[p-1] +grathist[p]

    output_q = np.zeros([256],np.uint8)
    cofficient = 256.0/(h*w)
    for p in range(256):
        q = cofficient *float(zerosumMoment[p]) - 1
        if q >= 0:
            output_q[p] = math.floor(q)
        else:
            output_q[p] = 0

    equalhistimage = np.zeros(img.shape,np.uint8)
    for i in range(h):
        for j in range(w):
            equalhistimage[i][j] = output_q[img[i][j]]

    # 第二种方法,opencv 库函数自带一种:
    #equalhistimage = cv2.equalizeHist(img)
    return equalhistimage

结果以下,看起来仍是不错的!(这里图片失真是由于灯光的缘由)

equalhist.png

5,小总结

根据以上几个加强方法来看,针对于本案例选取的图像,线性加强方法相对效果并不太好,可能会适用于其它的种类图像,而 Gamma转换  和直方图均衡化取得相对不错的结果

但图像加强、锐化没有最优方法,每种方法都有本身的特色,须要根据本身选择合适的

最后仍是要提醒一下感兴趣的小伙伴们,记得跟着敲一下代码,加深一下应用原理!



推荐阅读

不用 PS 抠图,Python + OpenCV  实现自动海报场景替换!

用 Python 对图片主体轮廓进行提取、颜色标记、并计算区域面积

本文分享自微信公众号 - Z先生点记(gh_683d048a482a)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。

相关文章
相关标签/搜索