RGB彩色图像的直方图和均衡化
对与RGB彩色图像,这里理解就是分为R、G、B三个通道,并不考虑保留图像的原有色调。每个通道的情况和灰度图像一样,都是用灰度值来衡量某个颜色的比重。对每个通道采用与上述代码相同的方法处理:(主要注意的是RGB图像在Mat中存储的顺序是BGR)
#include <cv.h>
#include <highgui.h>
using namespace cv;
// show histogram of grey image with sticks or continuous curve
void myShowHist(Mat & src, string winname, bool save = false, int style=0, int rows=400,int cols=512)
{
int histCnt[256]={0};
for(int y=0; y < src.rows; y++) {
for(int x=0; x < src.cols; x++) {
uchar grey=*(src.data+y*src.cols+x);
(histCnt[grey])++;
}
}
Mat histImage(rows,cols,CV_8UC3,Scalar(188,188,188));
int maxcnt=histCnt[0];
for(int i=0; i<=255; i++){
if(histCnt[i]>maxcnt) maxcnt=histCnt[i];
}
int lineType = 8;
if(style==0) { //sticks
int thickness = 1;
for(int i=0; i<=255; i++){
if(histCnt[i]!=0){
line(histImage,
Point((int)((float)i*(float)cols/256.0f),rows),
Point((int)((float)i*(float)cols/256.0f),rows-(int)((float)histCnt[i]*(float)rows/(float)maxcnt)),
Scalar(255,0,0),thickness,lineType);
}
}
}else{ // continuous curve
int thickness = 2;
int i=0;
int start=0;
while(histCnt[i]==0)
{
start=i;
i++;
}
for(i=start+1; i<=255; i++) {
int cnt=histCnt[i];
if(cnt!=0) {
line(histImage,
Point((int)((float)(start)*(float)cols/256.0f),rows-(int)((float)histCnt[start]*(float)rows/(float)maxcnt)),
Point((int)((float)i*(float)cols/256.0f),rows-(int)((float)cnt*(float)rows/(float)maxcnt)),
Scalar(255,0,0),thickness,lineType);
start=i;
}
}
}
namedWindow(winname);
imshow(winname, histImage);
if(save) imwrite(winname+".jpg",histImage);
}
// show histogram of RGB image with continuous curve
void myShowHistRGB(Mat & src, string winname,bool save = false, int rows=400,int cols=512)
{
// get dst histogram
int histCnt[3][256]={0};
for(int y=0; y < src.rows; y++) {
for(int x=0; x < src.cols; x++) {
for(int k=0; k<3; k++){
uchar grey=*(src.data+y*src.cols*3+x*3+k);
(histCnt[k][grey])++;
}
}
}
Mat hist(rows,cols,CV_8UC3,Scalar(188,188,188));
int maxcnt=histCnt[0][0];
for(int k=0; k<3; k++){
for(int i=0; i<=255; i++){
if(histCnt[k][i]>maxcnt) maxcnt=histCnt[k][i];
}
}
int thickness = 2;
int lineType = 8;
int k;
int i;
int start;// find where existed gery start
// B
k=0;
i=0;
start=0;
while(histCnt[k][i]==0)
{
start=i;
i++;
}
for(int i=start+1; i<=255; i++) {
int cnt=histCnt[k][i];
if(cnt!=0) {
line(hist,
Point((int)((float)(start)*(float)cols/256.0f),rows-(int)((float)histCnt[k][start]*(float)rows/(float)maxcnt)),
Point((int)((float)i*(float)cols/256.0f),rows-(int)((float)cnt*(float)rows/(float)maxcnt)),
Scalar(255,0,0),thickness,lineType);
start=i;
}
}
// G
k=1;
i=0;
start=0;
while(histCnt[k][i]==0)
{
start=i;
i++;
}
for(int i=start+1; i<=255; i++) {
int cnt=histCnt[k][i];
if(cnt!=0) {
line(hist,
Point((int)((float)(start)*(float)cols/256.0f),rows-(int)((float)histCnt[k][start]*(float)rows/(float)maxcnt)),
Point((int)((float)i*(float)cols/256.0f),rows-(int)((float)cnt*(float)rows/(float)maxcnt)),
Scalar(0,255,0),thickness,lineType);
start=i;
}
}
// R
k=2;
i=0;
start=0;
while(histCnt[k][i]==0)
{
start=i;
i++;
}
for(int i=start+1; i<=255; i++) {
int cnt=histCnt[k][i];
if(cnt!=0) {
line(hist,
Point((int)((float)(start)*(float)cols/256.0f),rows-(int)((float)histCnt[k][start]*(float)rows/(float)maxcnt)),
Point((int)((float)i*(float)cols/256.0f),rows-(int)((float)cnt*(float)rows/(float)maxcnt)),
Scalar(0,0,255),thickness,lineType);
start=i;
}
}
namedWindow(winname);
imshow(winname, hist);
if(save) imwrite(winname+".jpg",hist);
}
int main( void)
{
Mat src = imread("lena.jpg",1);
if(!src.data) return -1;
Mat dst = Mat::zeros(src.size(),src.type());
int rows=src.rows,cols=src.cols;
int srcHist[3][256]={0};
int tmpCDF[3][256]={0};
uchar mingrey[3]={255,255,255};
// get src histogram
for(int y=0; y < src.rows; y++) {
for(int x=0; x < src.cols; x++) {
for(int k=0; k<3; k++){
uchar grey=*(src.data+y*src.cols*3+x*3+k);
(srcHist[k][grey])++;
if(grey<=mingrey[k]) mingrey[k]=grey;
}
}
}
// get CDF
for( int k=0; k<3; k++) {
tmpCDF[k][0]=srcHist[k][0];
for(int i=1; i<=255; i++) {
tmpCDF[k][i]=tmpCDF[k][i-1]+srcHist[k][i];
}
}
// get dst
for(int y=0; y < dst.rows; y++) {
for(int x=0; x < dst.cols; x++) {
for(int k=0; k<3; k++){
uchar grey=*(src.data+y*src.cols*3+x*3+k);
if(tmpCDF[k][grey]!=0) {
float tmp=255.0f/(float)(rows*cols-srcHist[k][mingrey[k]]);
*(dst.data+y*dst.cols*3+x*3+k) = (uchar)((float)(tmpCDF[k][grey]-srcHist[k][mingrey[k]])*tmp);
}
}
}
}
// Show src
namedWindow("Src");
imshow("Src", src);
// Show dst
namedWindow("Dst");
imshow("Dst", dst);
myShowHistRGB(src,"SrcHist");
myShowHistRGB(dst,"DstHist");
imwrite("dst.jpg",dst);
// Wait until user press some key
waitKey();
return 0;
}
结果:
原图:结果图:
原图的彩色直方图:
结果的彩色直方图: