图像处理——直方图均衡化算法

前言:

直方图均衡化是灰度变换的一个重要应用,高效且易于实现。它通过改变图像的直方图来改变图像中各像素的灰度,主要用于增强动态范围偏小的图像的对比度。如果一幅图像整体偏暗或者偏亮,那么直方图均衡化的方法很适用。

一、OpenCV中直方图均衡化函数

调用自带的函数:cv2.equalizeHist
OpenCV中直方图均衡化算法的输入图像需为八位单通道图像,也就是灰度图像。若想要处计算彩色图像的均衡化图,可以先将图像用split函数进行通道分离,分别处理每一个通道的图像,在用merge函数进行合并。

import cv2
import numpy as np
img = cv2.imread('img.jpg', 1)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
dat = cv2.equalizeHist(gray)
cv2.imshow('gray', gray)a
cv2.imshow('dat', dat)
cv2.waitKey(0)

二、算法步骤

  1. 确定图像的灰度级;
  2. 计算原始直方图分布概率p(i);
  3. 计算直方图概率累计值s(i);
  4. 灰度映射;

三、python代码:

import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('img.jpg', 1)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
count = np.zeros(256, np.float)
for i in range(img.shape[0]):
    for j in range(img.shape[1]):
        count[int(gray[i, j])] += 1 # 统计该像素出现的次数
count = count / (img.shape[0] * img.shape[1]) # 得到概率
x = np.linspace(0,255,256)
plt.bar(x, count,color = 'b')
plt.show()

# 计算累计概率
for i in range(1,256):
    count[i] += count[i - 1]
# 映射
map1 = count * 255
for i in range(img.shape[0]):
    for j in range(img.shape[1]):
        p = gray[i, j]
        gray[i, j] = map1[p]
cv2.imshow('gray', gray)
cv2.waitKey(0)

四、C++代码:

#include <opencv2\opencv.hpp>
#include <iostream>

using namespace cv;

int main()
{
    
    
    Mat srcImg,grayImg;//声明原始图和灰度度
    srcImg = imread("1.jpg");//载入原始图
    if(!srcImg.data)
    {
    
    
        std::cout<<"请确认路径下存在图片";
        return -1;
    }
    imshow("原始图",srcImg);//显示原始图
    cvtColor(srcImg,grayImg,CV_RGB2GRAY);//将rgb图像转化为灰度图
    int rowNumber = grayImg.rows;//得到行
    int colNumber = grayImg.cols;//得到列
    int sumNumber = rowNumber*colNumber;//得到图像整个像素个数
    Mat dstImg(rowNumber,colNumber,CV_8UC1,Scalar(0,0,0));//初始化直方图均衡化后的图
    double hist[256] = {
    
    0.00};//直方图
    double dhist[256] = {
    
    0.00};//直方图归一化图
    double Dhist[256] = {
    
    0.00};//直方图积分图,每一个像素点
    for(int i = 0;i<rowNumber;i++)//遍历原始图像,得到直方图
    {
    
    
        uchar* data = grayImg.ptr<uchar>(i);
        for(int j = 0;j<colNumber;j++)
        {
    
    
            int temp = data[j];//得到图像像素值
            hist[temp] = hist[temp]+1;//将相应像素值在直方图中加1
        }
    }

    for(int i = 0;i<256;i++)//遍历直方图,得到归一化直方图和积分图
    {
    
           
        dhist[i] = hist[i]/sumNumber;//得到归一化图
        for(int j = 0;j<=i;j++)
        {
    
    
            Dhist[i] = Dhist[i] + dhist[j]; //得到积分图
        }
    }


    for(int i = 0;i<rowNumber;i++)//以积分图为查找表得到均衡化后的图
    {
    
    
        uchar* data1 = dstImg.ptr<uchar>(i);
        uchar* data2 = grayImg.ptr<uchar>(i);
        for(int j = 0;j<colNumber;j++)
        {
    
    
            int temp1 = data2[j]; //查找到原始图相应位置的像素值
            int temp2 = (int)(Dhist[temp1]*255); //在积分图中找到相应像素值的映射值
            data1[j] = temp2;//将映射值赋值给目标图像相应值
        }
    }
    imshow("均衡化后的图",dstImg);
    waitKey(0);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_42823043/article/details/109289294