颜色直方图
首先,先介绍一些Hist的基本使用。
官方文档:https://docs.opencv.org/trunk/d8/dbc/tutorial_histogram_calculation.html
利用OpenCV的calcHist绘制灰度直方图、H-S直方图、BGR直方图和自定义直方图的源码及说明
From: compare histograms of grayscale images in opencv
#include <opencv2/opencv.hpp> void show_histogram(std::string const& name, cv::Mat1b const& image) { // Set histogram bins count int bins = 256; int histSize[] = {bins}; // Set ranges for histogram bins float lranges[] = {0, 256}; const float* ranges[] = {lranges}; // create matrix for histogram cv::Mat hist; int channels[] = {0}; // create matrix for histogram visualization int const hist_height = 256; cv::Mat3b hist_image = cv::Mat3b::zeros(hist_height, bins); cv::calcHist(&image, 1, channels, cv::Mat(), hist, 1, histSize, ranges, true, false); double max_val=0; minMaxLoc(hist, 0, &max_val); // visualize each bin for(int b = 0; b < bins; b++) { float const binVal = hist.at<float>(b); int const height = cvRound(binVal*hist_height/max_val); cv::line ( hist_image , cv::Point(b, hist_height-height), cv::Point(b, hist_height) , cv::Scalar::all(255) ); } cv::imshow(name, hist_image); } int main (int argc, const char* argv[]) { // here you can use cv::IMREAD_GRAYSCALE to load grayscale image, see image2 cv::Mat3b const image1 = cv::imread("C:\\workspace\\horse.png", cv::IMREAD_COLOR); cv::Mat1b image1_gray; cv::cvtColor(image1, image1_gray, cv::COLOR_BGR2GRAY); cv::imshow("image1", image1_gray); show_histogram("image1 hist", image1_gray); cv::Mat1b const image2 = cv::imread("C:\\workspace\\bunny.jpg", cv::IMREAD_GRAYSCALE); cv::imshow("image2", image2); show_histogram("image2 hist", image2); cv::waitKey(); return 0; }
Histogram equalization
线性混合算子
非线性算子
覆盖算子
直方图均衡化
直方图的观看规则就是“左黑右白”,左边代表暗部,右边代表亮部,而中间则代表中间调。 纵向上的高度代表像素密集程度,越高,代表的就是分布在这个亮度上的像素很多。
对比度
对比度在直方图上的体现就是高光和阴影部分都有像素。
它可以很少,但是必须有,否则照片看起来就很灰了。正常照片变为低对比度后的直方图对比:
当然,也有看起来不错的低对比度图片,但它的直方图不会像上图那样极端,一般都是没有纯黑,但高光都比较足:
均衡化
(a) vs (e) 对比度有所加强。
However,可能放大暗区域的噪声。
它的基本思想是对图像中像素个数多的灰度级进行展宽,而对图像中像素个数少的灰度进行压缩,从而扩展像原取值的动态范围,提高了对比度和灰度色调的变化,使图像更加清晰。
http://blog.csdn.net/xiaowei_cqu/article/details/7606607
从分布图上的理解就是希望原始图像中y轴的值在新的分布中尽可能的展开。
变换过程是利用累积分布函数对原始分布进行映射,生成新的均匀拉伸的分布。
因此,对应每个点的操作是寻找原始分布中y值在均匀分布中的位置,如下图是理想的单纯高斯分布映射的示意图:
int main() { IplImage * image= cvLoadImage("baboon.jpg"); //显示原图及直方图 myShowHist("Source",image); IplImage* eqlimage=cvCreateImage(cvGetSize(image),image->depth,3); //分别均衡化每个信道 IplImage* redImage=cvCreateImage(cvGetSize(image),image->depth,1); IplImage* greenImage=cvCreateImage(cvGetSize(image),image->depth,1); IplImage* blueImage=cvCreateImage(cvGetSize(image),image->depth,1); cvSplit(image,blueImage,greenImage,redImage,NULL); cvEqualizeHist(redImage,redImage); cvEqualizeHist(greenImage,greenImage); cvEqualizeHist(blueImage,blueImage); //均衡化后的图像 cvMerge(blueImage,greenImage,redImage,NULL,eqlimage); myShowHist("Equalized",eqlimage); }