C++ OpenCV 컬러 흑백 이미지 Histogram(히스토그램)

2021. 1. 8. 09:00OpenCV/OpenCV C++

반응형

1. 흑백 이미지 히스토그램

히스토그램은 이미지의 밝기 값이 0~255 까지 있을 때, 픽셀들이 얼마나 그 값들으 갖고 있는지 나타내주는 그래프 이다.

OpenCV에서는 이미지의 히스토그램 계산이 쉽도록 함수 calcHist()를 제공한다.

void cv::calcHist(const Mat*    images, // Histogram을 계산할 이미지들에 대한 배열이다.
                  int           nimages, // images 배열에 포함된 이미지의 개수이다.
                  const int*    channels, //Histogram을 계산할 채널 번호들의 배열이다.
                  InputArray    mask, //Histogram을 계산할 영역을 지정할 수 있다.
                  OutputArray   hist, //Histogram 계산결과를 저장한다.
                  int           dims, //Histogram 계산결과를 저장한 hist의 차원으 가리킨다.
                  const int*    histSize, //각 차원의 bin개수, 즉 빈도수를 분류할 칸의 개수를 의미한다.
                  const float** ranges, //각 차원의 분류 bin의 최소값 최대값을 의미한다.
                  bool          uniform =true,
                  bool          accumulate = flase
                 )

 

실행코드

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

using namespace cv;
using namespace std;

int main(int ac, char** av) {

    Mat img_1 = imread("Lenna.png", 0);    //이미지를 grayscale로 불러옴

    Mat img_2 = img_1 * 2;
    Mat img_3 = img_1 / 2;
    Mat img_hist;

    MatND histogram;

    const int* channel_numbers = { 0 };
    float channel_range[] = { 0.0, 255.0 };
    const float* channel_ranges = channel_range;
    int number_bins = 255;

    calcHist(&img_1, 1, channel_numbers, Mat(), histogram, 1, &number_bins, &channel_ranges);

    // plot the histogram
    int hist_w = img_1.cols;
    int hist_h = img_1.rows;
    int bin_w = cvRound((double)hist_w / number_bins);

    Mat hist_img(hist_h, hist_w, CV_8UC1, Scalar::all(0));
    normalize(histogram, histogram, 0, hist_img.rows, NORM_MINMAX, -1, Mat());

    for (int i = 1; i < number_bins; i++)
    {
        line(hist_img, Point(bin_w * (i - 1), hist_h - cvRound(histogram.at<float>(i - 1))), Point(bin_w * (i), hist_h - cvRound(histogram.at<float>(i))), Scalar(255, 0, 0), 1, 8, 0);
    }

    imshow("Origianl", img_1);
    imshow("Histogram", hist_img);



    //imshow("original", img_1);
    //imshow("img_mul", img_2);
    //imshow("img_div", img_3);

    waitKey(0);


    return 0;
}

 

결과

1



2. 컬러 이미지 히스토그램

실행 코드

#include<iostream>
#include<opencv2\core.hpp>
#include<opencv\cv.h>
#include<opencv2\highgui.hpp>
#include<opencv2\imgproc.hpp>
#include <stdio.h>

using namespace cv;
using namespace std;

int main(int ac, char** av) {
    Mat inputImg = imread("Lenna.png", CV_LOAD_IMAGE_COLOR);

    MatND histogramB, histogramG, histogramR;
    int channel_B[] = { 0 };  // Blue
    int channel_G[] = { 1 };  // Green
    int channel_R[] = { 2 };  // Red
    float channel_range[2] = { 0.0 , 255.0 };
    const float* channel_ranges[1] = { channel_range };
    int histSize[1] = { 256 };

    // R, G, B별로 각각 히스토그램을 계산한다.
    calcHist(&inputImg, 1, channel_B, Mat(), histogramB, 1, histSize, channel_ranges);
    calcHist(&inputImg, 1, channel_G, Mat(), histogramG, 1, histSize, channel_ranges);
    calcHist(&inputImg, 1, channel_R, Mat(), histogramR, 1, histSize, channel_ranges);

    // Plot the histogram
    int hist_w = 512; int hist_h = 400;
    int bin_w = cvRound((double)hist_w / histSize[0]);

    Mat histImageB(hist_h, hist_w, CV_8UC3, Scalar(0, 0, 0));
    normalize(histogramB, histogramB, 0, histImageB.rows, NORM_MINMAX, -1, Mat());

    Mat histImageG(hist_h, hist_w, CV_8UC3, Scalar(0, 0, 0));
    normalize(histogramG, histogramG, 0, histImageG.rows, NORM_MINMAX, -1, Mat());

    Mat histImageR(hist_h, hist_w, CV_8UC3, Scalar(0, 0, 0));
    normalize(histogramR, histogramR, 0, histImageR.rows, NORM_MINMAX, -1, Mat());

    for (int i = 1; i < histSize[0]; i++)
    {
        line(histImageB, Point(bin_w * (i - 1), hist_h - cvRound(histogramB.at<float>(i - 1))),
            Point(bin_w * (i), hist_h - cvRound(histogramB.at<float>(i))),
            Scalar(255, 0, 0), 2, 8, 0);

        line(histImageG, Point(bin_w * (i - 1), hist_h - cvRound(histogramG.at<float>(i - 1))),
            Point(bin_w * (i), hist_h - cvRound(histogramG.at<float>(i))),
            Scalar(0, 255, 0), 2, 8, 0);

        line(histImageR, Point(bin_w * (i - 1), hist_h - cvRound(histogramR.at<float>(i - 1))),
            Point(bin_w * (i), hist_h - cvRound(histogramR.at<float>(i))),
            Scalar(0, 0, 255), 2, 8, 0);

    }

    namedWindow("Original", CV_WINDOW_AUTOSIZE);
    namedWindow("HistogramB", CV_WINDOW_AUTOSIZE);
    namedWindow("HistogramG", CV_WINDOW_AUTOSIZE);
    namedWindow("HistogramR", CV_WINDOW_AUTOSIZE);

    moveWindow("Original", 100, 100);
    moveWindow("HistogramB", 110, 110);
    moveWindow("HistogramG", 120, 120);
    moveWindow("HistogramR", 130, 130);

    imshow("Original", inputImg);
    imshow("HistogramB", histImageB);
    imshow("HistogramG", histImageG);
    imshow("HistogramR", histImageR);

    waitKey(0);
    return 0;
}

 

결과

2



3. 흑백 이미지와 컬러 이미지 히스토그램 그리기의 차이점

흑백이미지는 채널을 하나로 계산하면 되지만 컬러이미지는 B, G, R 채널별로 동일한 작업으로 반복해야 한다.

 

참고 사이트

 

[C++ opencv] 효율적인 Histogram 이용한 이미지 밝기 조절

본문 목표 이미지의 Histogram 정보를 통해서 이미지의 밝기를 효과적으로 조절할 수 있다. OpenCV 에서도 해당 기능을 지원하는데, 이를 적용해보도록 한다. 키워드 : equalizeHist, Histogram equalization, 히

diyver.tistory.com

 

반응형

'OpenCV > OpenCV C++' 카테고리의 다른 글

C++ OpenCV Labeling  (0) 2021.01.20
C++ OpenCV Transformation  (0) 2021.01.18
C++ OpenCV Segmentation and Labelging  (0) 2021.01.11
C++ OpenCV 이미지 전처리  (0) 2021.01.04
C++ OpenCV라이브러리 설치 방법  (0) 2020.12.31