python实现clahe对比度增强

一、获取直方图

def hist_cal(img):
    img = np.array(img)
    heigh,width=img.shape
    histogram=np.zeros(256)
    for i in range(heigh):
        for j in range(width):
            gray = img[i][j]
            histogram[gray] += 1#出现某个像素值则加1,最终统计出各个像素值的频数

    return histogram

二、累积分布函数

def EqualizeHistogram(img,histogram,LIMIT = 200):
    img = np.array(img)
    heigh, width = img.shape
    pixcount=heigh * width
    dataOfSrc = img
    dataOfDst=np.zeros([heigh, width])   
    steal = 0
    for k in range(256):
        if histogram[k]>LIMIT:
            histogram[k]=LIMIT
            steal+= histogram[k]-LIMIT
    bonus=math.floor(steal/256)
    for l in range(256):
        histogram[l]+=bonus
    pro_den=histogram/pixcount
    sum=0
    LUT=np.zeros(256)
    for i in range(256):
        sum+=pro_den[i]
        LUT[i]=sum * 255
    for m in range(heigh):
        for n in range(width):
            dataOfDst[m][n]=LUT[dataOfSrc[m][n]]
    Equalize_img=dataOfDst.reshape([heigh, width])
    Equalize_img=Equalize_img.astype(np.uint8)
    return LUT,Equalize_img
    #返回两个值,前者用于AHE、CLAHE的插值,后者用于直方图均衡化直接使用

三、双线性插值

def CLAHE(block_number,img_gray):
    heigh, width = img_gray.shape
    img_ahe_liner = np.zeros([heigh, width])
    block_height = heigh // block_number
    block_width = width // block_number
    all_LUT = np.zeros([block_number, block_number, 256])  # 存储累积分布函数
    # 求得各个块的累积分布函数
    for i in range(block_number):
        for j in range(block_number):
            block = img_gray[i * block_height:(i + 1) * block_height, j * block_width:(j + 1) * block_width]
            hist_block = hist_cal(block)
            all_LUT[i, j], Equalize_hist = EqualizeHistogram(block, hist_block)
    for m in range(heigh):
        for n in range(width):
            # four coners
            # 在角上的像素点为累积分布函数得到的值
            if m <= block_height / 2 and n <= block_width / 2:
                block_m = 0
                block_n = 0
                img_ahe_liner[m, n] = all_LUT[block_m, block_n][img_gray[m, n]]
            elif m <= block_height / 2 and n >= width - block_width / 2:
                block_m = 0
                block_n = block_number - 1
                img_ahe_liner[m, n] = all_LUT[block_m, block_n][img_gray[m, n]]
            elif n <= block_width / 2 and m >= heigh - block_height / 2:
                block_m = block_number - 1
                block_n = 0
                img_ahe_liner[m, n] = all_LUT[block_m, block_n][img_gray[m, n]]
            elif m >= heigh - block_height / 2 and n >= width - block_width / 2:
                block_m = block_number - 1
                block_n = block_number - 1
                img_ahe_liner[m, n] = all_LUT[block_m, block_n][img_gray[m, n]]
            # four edges except coners
            # 四个边采取线性插值
            elif n <= block_width / 2:
                block_m_1 = math.floor((m - block_height / 2) / block_height)
                block_n_1 = 0
                block_m_2 = block_m_1 + 1
                block_n_2 = block_n_1
                u = np.float((m - (block_m_1 * block_height + block_height / 2)) / (block_height))
                v = 1 - u
                img_ahe_liner[m, n] = v * all_LUT[block_m_1, block_n_1][img_gray[m, n]] + \
                                      u * all_LUT[block_m_2, block_n_2][img_gray[m, n]]
            elif m <= block_height / 2:
                block_m_1 = 0
                block_n_1 = math.floor((n - block_width / 2) / block_width)
                block_m_2 = block_m_1
                block_n_2 = block_n_1 + 1
                u = np.float((n - (block_n_1 * block_width + block_width / 2)) / (block_width))
                v = 1 - u
                img_ahe_liner[m, n] = v * all_LUT[block_m_1, block_n_1][img_gray[m, n]] + \
                                      u * all_LUT[block_m_2, block_n_2][img_gray[m, n]]
            elif m >= heigh - block_height / 2:
                block_m_1 = block_number - 1
                block_n_1 = math.floor((n - block_width / 2) / block_width)
                block_m_2 = block_m_1
                block_n_2 = block_n_1 + 1
                u = np.float((n - (block_n_1 * block_width + block_width / 2)) / (block_width))
                v = 1 - u
                img_ahe_liner[m, n] = v * all_LUT[block_m_1, block_n_1][img_gray[m, n]] + \
                                      u * all_LUT[block_m_2, block_n_2][img_gray[m, n]]
            elif n >= width - block_width / 2:
                block_m_1 = math.floor((m - block_height / 2) / block_height)
                block_n_1 = block_number - 1
                block_m_2 = block_m_1 + 1
                block_n_2 = block_n_1
                u = np.float((m - (block_m_1 * block_height + block_height / 2)) / (block_height))
                v = 1 - u
                img_ahe_liner[m, n] = v * all_LUT[block_m_1, block_n_1][img_gray[m, n]] + \
                                      u * all_LUT[block_m_2, block_n_2][img_gray[m, n]]
            # 中间区域采取双线性插值
            else:
                block_m_1 = math.floor((m - block_height / 2) / block_height)
                block_n_1 = math.floor((n - block_width / 2) / block_width)
                block_m_2 = block_m_1 + 1
                block_n_2 = block_n_1 + 1
                u = np.float((m - (block_m_1 * block_height + block_height / 2)) / (block_height))
                v = np.float((n - (block_n_1 * block_width + block_width / 2)) / (block_width))
                img_ahe_liner[m, n] = (1 - u) * (1 - v) * all_LUT[block_m_1, block_n_1][img_gray[m, n]] + \
                                      v * (1 - u) * all_LUT[block_m_1, block_n_2][img_gray[m, n]] + \
                                      u * (1 - v) * all_LUT[block_m_2, block_n_1][img_gray[m, n]] + \
                                      u * v * all_LUT[block_m_2, block_n_2][img_gray[m, n]]
    return img_ahe_liner.astype(np.uint8)

如果不采用插值,最终的结果将会有很明显边界。

四、主函数

im=cv2.imread('040a07b4c00a844_size196_w640_h480.jpg')
img_LAB = cv2.cvtColor(im,cv2.COLOR_BGR2LAB)
lab_planes  = cv2.split(img_LAB)#转化为LAB颜色域,对light分量进行CLAHE,可以得到彩色图,如果转化为灰度图,则是对灰度颜色域的CLAHE
lab_planes[0]=CLAHE(8,lab_planes[0])
lab = cv2.merge(lab_planes)
bgr = cv2.cvtColor(lab, cv2.COLOR_LAB2BGR)
cv2.namedWindow("img_gray",0)
cv2.imshow("img_gray",img_LAB)
cv2.resizeWindow("img_gray",640,480)
cv2.namedWindow("Equalize_img",0)
cv2.resizeWindow("Equalize_img",640,480)
cv2.imshow("Equalize_img",bgr)
cv2.waitKey()

五、使用的库

import numpy as np 
import cv2 
import math

六、与官方函数的对比

使用CV2中的函数:

import cv2

mri_img = cv2.imread('040a07b4c00a844_size196_w640_h480.jpg')

lab = cv2.cvtColor(mri_img, cv2.COLOR_BGR2LAB)

lab_planes = cv2.split(lab)

clahe = cv2.createCLAHE(clipLimit=10,tileGridSize=(8,8))

lab_planes[0] = clahe.apply(lab_planes[0])

lab = cv2.merge(lab_planes)

bgr = cv2.cvtColor(lab, cv2.COLOR_LAB2BGR)
cv2.namedWindow("p",0)
cv2.resizeWindow("p",640,480)
cv2.imshow('p',bgr)
cv2.waitKey(0)

图1为原图,图2为cv2库得到,图三为自己代码实现:
在这里插入图片描述
图1 原图
图2 cv2 库得到
图2 cv2库得到

在这里插入图片描述
图三 自己代码实现
官方库运行速度快,自己代码写的for循环太多,耗时较长,采取矩阵运算的方式应该会快很多。

  • 6
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值