OpenCV-直方图、直方图均衡化、自适应直方图均衡化

在图像处理中,灰度直方图能反映一幅图像的灰度级信息。灰度直方图是图像灰度级的函数,用来描述该幅图像中像素个数或者占有率。
C++:

#include<opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
//计算图像灰度直方图
Mat calcgrayhist(const Mat&image)
{
	Mat histogram = Mat::zeros(Size(256, 1), CV_32SC1);
	//图像宽高
	int rows = image.rows;
	int cols = image.cols;
	for (int i = 0; i < rows; i++)
	{
		for (int j = 0; j < rows; j++)
		{
			int index = int(image.at<uchar>(i, j));
			histogram.at<int>(0, index) += 1;
		}
	}
	return histogram;
};

//直方图均衡化
Mat equalhist(Mat image)
{	
	int rows = image.rows;
	int cols = image.cols;
	//1.计算图像灰度直方图
	Mat grayhist = calcgrayhist(image);
	//2.计算累加灰度直方图
	Mat accumulate_hist = Mat::zeros(Size(256, 1), CV_32SC1);
	for (int p = 0; p < 256; p++)
	{
		if (p == 0)
			accumulate_hist.at<int>(0, p) = grayhist.at<int>(0, 0);
		else
			accumulate_hist.at<int>(0, p)= accumulate_hist.at<int>(0, p-1)+
			grayhist.at<int>(0, p);
	}
	//3.映射
	Mat out_p=Mat::zeros(Size(256, 1), CV_8UC1);
	float cofficient = 256.0 / (rows*cols);
	for (int p = 0; p < 256; p++)
	{
		float q = cofficient*accumulate_hist.at<int>(0, p) - 1;
		if (q >= 0)
			out_p.at<uchar>(0, p) = uchar(floor(q));
		else
			out_p.at<uchar>(0, p) = 0;
		
	}
	Mat equalhistimage= Mat::zeros(image.size(), CV_8UC1);
	for (int i = 0; i < rows; i++)
	{
		for (int j = 0; j < cols; j++)
		{
			int p = image.at<uchar>(i, j);
			equalhistimage.at<uchar>(i, j) =out_p.at<uchar>(0, p);
		}
	}
	return equalhistimage;
};

//自适应直方图均衡化
Mat adapt_equalhist(Mat image)
{
	Ptr<CLAHE>clahe = createCLAHE(2.0, Size(8, 8));
	Mat dst;
	clahe->apply(image, dst);
	//imshow("original image", image);
	//imshow("adapt image", dst);
	//waitKey(0);
	return dst;
};
int main()
{
	Mat img, gray_img,src,dst;
	img = imread("D:/testimage/scenery.jpg");
	cvtColor(img, gray_img, COLOR_BGR2GRAY);
	src = equalhist(gray_img);
	dst=adapt_equalhist(gray_img);
	imshow("equal image", src);
	imshow("adapt equalimage", dst);
	waitKey(0);
	return 0;
};

结果:
原图彩色直方图:
彩色直方图直方图均衡化:
直方图均衡化自适应直方图均衡化:
自适应直方图均衡化在这张图像上,两者看不出明显的变化,除了在天空云层的那一块,自适应一般是为了保留一些细节,防止整个图像都按照原函数处理,可能达不到要求。

Python:

import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
import math

def calc_grayhist(image):
    #图像宽高
    rows,cols=image.shape
    grayhist=np.zeros([256],np.uint64)
    for i in range(rows):
        for j in range(cols):
            grayhist[image[i][j]]+=1
    return grayhist

#彩色图像支方图
def calc_colorhist(src):
    channels=cv.split(src);
    colors=('B','G','R')
    plt.xlabel=("grays level")
    plt.ylabel=("pixels")
    for (channel,color) in zip(channels,colors):
        hist=cv.calcHist([channel],[0], None, [256], [0, 256])
        plt.plot(hist, color=color)
        plt.xlim([0, 256])
    plt.show()

#直方图均衡化
def equalhist(image):
    # 图像宽高
    rows, cols = image.shape
    grayhist=calc_grayhist(image)
    # 计算累加灰度直方图
    Accumulate_histogram=np.zeros([256],np.uint32)
    for p in range (256):
        if p ==0:
            Accumulate_histogram[p]=grayhist[0]
        else:
            Accumulate_histogram[p]=Accumulate_histogram[p-1]+grayhist[p]
    #根据累加直方图得到输入灰度级和输出灰度级之间的映射关系
    out_q=np.zeros([256],np.uint8)
    cofficient=256.0/(rows*cols)
    for p in range(256):
        q=cofficient*float(Accumulate_histogram[p])-1
        if q>=0:
            out_q[p]=math.floor(q)
        else:
            out_q[p]=0
    #直方图均衡图像
    equalhist_image=np.zeros(image.shape,np.uint8)
    for i in range(rows):
        for j in range(cols):
            equalhist_image[i][j]=out_q[image[i][j]]
    return equalhist_image

#自适应直方图均衡化
def adapt_equalhist(image):
    #clipLimit参数表示对比度的大小。
    #tileGridSize参数表示每次处理块的大小
    clahe=cv.createCLAHE(clipLimit=2,tileGridSize=(8,8))
    dst=clahe.apply(image)
    return dst


if __name__=="__main__":
    img=cv.imread("D:/testimage/scenery.jpg")
    gray_dst = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
    calc_grayhist(gray_dst)
    calc_colorhist(img)
    equal_dst=equalhist(gray_dst)
    adapt_equaldst=adapt_equalhist(gray_dst)
    cv.imshow("gray dst",gray_dst)
    cv.imshow("equal dst", equal_dst)
    cv.imshow("adapt equaldst", adapt_equaldst)
    cv.waitKey(0)
    cv.destroyAllWindows()

今日头条-witnesS

  • 1
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值