数字图像处理14--OpenCV彩色图像的直方图均衡化, C++

先均衡化一下图像亮度看看情况,方法:由BGR-->YCrCb--->均衡化Y--->BGR

代码如下:


#include <iostream>
#include <string>

#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"

const char* keys =
{
    "{help h usage ? | | print this message}"
        "{@image | | Image to process}"
};

cv::Mat equalize_y_channel( cv::Mat &src_img )
{
    cv::Mat result;
    cv::Mat ycrcb;

    cv::cvtColor( src_img, ycrcb, cv::COLOR_BGR2YCrCb);

    std::vector<cv::Mat> channels;
    cv::split( ycrcb, channels );

    //only equalize y
    cv::equalizeHist( channels[0], channels[0] );

    cv::merge( channels, ycrcb );

    cv::cvtColor( ycrcb, result, cv::COLOR_YCrCb2BGR );
//    imshow( "Equalize", result );
    return result;
}

cv::Mat show_histograms( cv::Mat &src_img )
{
    //split image to 3 channels
    std::vector<cv::Mat> bgr;
    cv::split( src_img, bgr );

    //create 256 subinterval
    //the number of possibles values
    int numbins = 256;

    //set the range for BGR(0-256)
    float range[] = { 0, 256};
    const float* histRange = { range };

    cv::Mat b_hist, g_hist, r_hist;

    cv::calcHist( &bgr[0], 1, 0, cv::Mat(), b_hist, 1, &numbins, &histRange );
    cv::calcHist( &bgr[1], 1, 0, cv::Mat(), g_hist, 1, &numbins, &histRange );
    cv::calcHist( &bgr[2], 1, 0, cv::Mat(), r_hist, 1, &numbins, &histRange );

    //draw histogram
    //draw lines for each channels
    int width = 512;
    int height = 300;

    // Create image with gray base
    cv::Mat histImage( height, width, CV_8UC3, cv::Scalar(20, 20, 20) );

    // Normalize the histograms to height of image
    cv::normalize(b_hist, b_hist, 0, height, cv::NORM_MINMAX );
    cv::normalize(g_hist, g_hist, 0, height, cv::NORM_MINMAX );
    cv::normalize(r_hist, r_hist, 0, height, cv::NORM_MINMAX );

    int binStep= cvRound((float)width/(float)numbins);
    for( int i=1; i< numbins; i++)
    {
        cv::line( histImage,
        cv::Point( binStep*(i-1), height-cvRound(b_hist.at<float>(i-1) ) ),
        cv::Point( binStep*(i), height-cvRound(b_hist.at<float>(i) ) ),
                cv::Scalar(255,0,0)
        );
        line( histImage,
            cv::Point( binStep*(i-1), height-cvRound(g_hist.at<float>(i-1) ) ),
            cv::Point( binStep*(i), height-cvRound(g_hist.at<float>(i) ) ),
            cv::Scalar(0,255,0)
        );
        line( histImage,
            cv::Point( binStep*(i-1), height-cvRound(r_hist.at<float>(i-1) ) ),
            cv::Point( binStep*(i), height-cvRound(r_hist.at<float>(i) ) ),
            cv::Scalar(0,0,255)
        );
    }
//    cv::imshow("Histogram", histImage);
    return histImage;
}

int main( int argc, const char** argv )
{
    cv::CommandLineParser parser(argc, argv, keys);
    parser.about("Chapter 4. PhotoTool v1.0.0");
    //If requires help show
    if (parser.has("help")){
        parser.printMessage();
        return 0;
    }

    cv::String imgFile= parser.get<cv::String>(0);

    // Check if params are correctly parsed in his variables
    if (!parser.check()){
        parser.printErrors();
        return 0;
    }

    // Load image to process
    cv::Mat img= cv::imread(imgFile);
    if( !img.data ){
        std::cerr << "Can't read image" << std::endl;
        return -1;
    }
    // Create window
    cv::namedWindow("Input");


    cv::Mat hist_img1 = show_histograms(img);
    cv::Mat equa_img1 = equalize_y_channel(img);
    cv::Mat hist_img2 = show_histograms(equa_img1);

    // Show image
    cv::imshow("Input", img);
    cv::imshow("hist_img1", hist_img1);
    cv::imshow("equa_img1", equa_img1);
    cv::imshow("hist_img2", hist_img2);

    cv::waitKey(0);
    return 0;

}
 

结果如下:

可见只均衡化亮度对BGR图像来说没什么意义;下面分别均衡化BGR通道;

代码如下:

/*
 * color_equalizehist.cpp
 *
 *  Created on: May 20, 2018
 *      Author: cui
 */


#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

#include <iostream>
#include <stdio.h>

using namespace cv;
using namespace std;

void histogram_calculation( const Mat &Image, Mat &histoImage )
{
    // Create the histogram for 256 bins
    // The number of possibles values
    int histSize= 255;

    /// Set the ranges ( for B,G,R) )
    float range[] = { 0, 256 } ;
    const float* histRange = { range };

    bool uniform = true;
    bool accumulate = false;

    Mat b_hist, g_hist, r_hist;

    vector<Mat>  bgr_planes;
    split( Image, bgr_planes );

    calcHist( &bgr_planes[0], 1, 0, Mat(), b_hist, 1, &histSize,
            &histRange, uniform, accumulate );
    calcHist( &bgr_planes[1], 1, 0, Mat(), g_hist, 1, &histSize,
            &histRange, uniform, accumulate );
    calcHist( &bgr_planes[2], 1, 0, Mat(), r_hist, 1, &histSize,
            &histRange, uniform, accumulate );

    // Draw the histogram
    // We go to draw lines for each channel
    int hist_w= 512;
    int hist_h= 400;

    int bin_w= cvRound((float)hist_w/(float)histSize);

    // Create image with gray base
    Mat histImage( hist_h, hist_w, CV_8UC3, Scalar(0,0,0) );

    // Normalize the histograms to height of image
   normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
   normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
   normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );

   for( int i=1; i< histSize; i++){
       line( histImage,
               Point( bin_w*(i-1), hist_h-cvRound(b_hist.at<float>(i-1) ) ),
               Point( bin_w*(i), hist_h-cvRound(b_hist.at<float>(i) ) ),
               Scalar(255,0,0), 2, 8, 0
           );
       line( histImage,
               Point( bin_w*(i-1), hist_h-cvRound(g_hist.at<float>(i-1) ) ),
               Point( bin_w*(i), hist_h-cvRound(g_hist.at<float>(i) ) ),
               Scalar(0,255,0), 2, 8, 0
           );
       line( histImage,
               Point( bin_w*(i-1), hist_h-cvRound(r_hist.at<float>(i-1) ) ),
               Point( bin_w*(i), hist_h-cvRound(r_hist.at<float>(i) ) ),
               Scalar(0,0,255), 2, 8, 0
           );
   }

//   imshow("Histogram", histImage);
   histoImage = histImage;

}

int main( int argc, char *argv[] )
{
    Mat src, imageq;
    Mat histImage;

    //get src image
    src = imread( "lena.jpg" );
    if( src.empty() ){
        fprintf( stderr, "Error image, can't load\n" );
        exit(-1);
    }

    vector<Mat> bgr;
    split( src, bgr );

    Size src_s = src.size();
    cout << "fruits.jpg rows: " << src.rows << endl;
    cout << "fruits.jpg cols: " << src.cols << endl;  
    cout << "fruits.jpg size.width: " << src_s.width << endl;
    cout << "fruits.jpg size.height: " << src_s.height << endl; 
    imshow( "Source image", src );
    cout << "Source image show end" << endl;
    //calculate src channel equalize
    histogram_calculation( src, histImage);

    cout << "histImage rows: " << histImage.rows << endl;
    cout << "histImage cols: " << histImage.cols << endl;
    imshow( "Color Image Histogram", histImage );

    //equalize image
    equalizeHist( bgr[0], bgr[0] );
    equalizeHist( bgr[1], bgr[1] );
    equalizeHist( bgr[2], bgr[2] );

    merge( bgr, imageq);
    imshow( "Equalized image", imageq );

    //calculate every channel histogram
    histogram_calculation( imageq, histImage );
    imshow( "Equalized color image histogram", histImage );

    waitKey(0);
    return 0;
}
 

效果如下:

图像更艳丽了。。。。。。

猜你喜欢

转载自blog.csdn.net/cyf15238622067/article/details/87798128