天天看點

OpenCV + CPP 系列(十八)直方圖 與 直方圖均衡化

文章目錄

  • ​​一、函數介紹​​
  • ​​calcHist​​
  • ​​cvRound()、cvFloor()、cvCeil()函數詳解​​
  • ​​二、直方圖顯示​​
  • ​​一維直方圖​​
  • ​​二維直方圖​​
  • ​​三、直方圖均衡化​​

關于opencv-python 有關直方圖檢視

OpenCV—python 顔色空間(RGB,HSV,Lab)與 顔色直方圖

OpenCV—python 顔色直方圖與直方圖均衡化

一、函數介紹

calcHist

該函數可以一次統計多張圖檔每個通道的灰階值資料

const

Mat*

​images​

​,    輸入需要計算的矩陣(CV_8U或 CV_32F)

int

​nimages​

​,       源圖像的數目

const int*

​channels​

​,    通道清單。通道數必須與直方圖維數比對,從0開始

InputArray

​mask​

​,     掩碼(不需要填Mat())

OutputArray

​hist​

​,    輸出直方圖

int

​dims​

​,        直方圖的次元

const int*

​histSize​

​,   數組,即histSize[i]表示第i個次元上bin的個數(一維一般為256)

const float**

​ranges​

​,   一般為(0,256)

bool

​uniform = true​

​,   辨別,用于說明直方條bin是否是均勻等寬的。

bool

​accumulate = false​

​ 累積辨別。多幅圖像時,累積計算一個簡單的直方圖,或者及時更新直方圖。

)

cvRound()、cvFloor()、cvCeil()函數詳解

函數cvRound()、cvFloor()、cvCeil()都是按照一種舍入方式将浮點型資料轉換為整型資料。

  • cvRound():傳回跟參數最接近的整數值,即四舍五入;(2.5 ->2, 2.51->3)
  • cvFloor() :傳回不大于參數的最大整數值,即向下取整;(2.5 ->2)
  • cvCeil() :傳回不小于參數的最小整數值,即向上取整;(2.5 ->3)

二、直方圖顯示

頭檔案 ​

​quick_opencv.h​

​:聲明類與公共函數

#pragma once
#include <opencv2\opencv.hpp>
using namespace cv;

class QuickDemo {
public:
  ...
  void show_histogram_Demo(Mat& image);
  void show_histogram2d_Demo(Mat& image);
};      

主函數調用該類的公共成員函數

#include <opencv2\opencv.hpp>
#include <quick_opencv.h>
#include <iostream>
using namespace cv;


int main(int argc, char** argv) {
  Mat src = imread("D:\\Desktop\\pandas.jpg");
  if (src.empty()) {
    printf("Could not load images...\n");
    return -1;
  }
  namedWindow("input", WINDOW_NORMAL);
  imshow("input", src);

  QuickDemo qk;

  ...
  qk.show_histogram_Demo(src);
  qk.show_histogram2d_Demo(src);
  waitKey(0);
  destroyAllWindows();
  return 0;
}      

一維直方圖

源檔案 ​

​quick_demo.cpp​

​:實作類與公共函數

void QuickDemo::show_histogram_Demo(Mat& image) {
  std::vector<Mat> bgr_plane;
  split(image, bgr_plane);

  const int channels[1] = { 0 };
  const int bins[1] = { 256 };    //bins資料分成的等級
  float hranges[2] = { 0,256 };
  const float* ranges[1] = { hranges };

  Mat b_hist;
  Mat g_hist;
  Mat r_hist;

  // 計算 B,G,R三個通道的直方圖
  calcHist(&bgr_plane[0], 1, 0, Mat(), b_hist, 1, bins, ranges);
  calcHist(&bgr_plane[1], 1, 0, Mat(), g_hist, 1, bins, ranges);
  calcHist(&bgr_plane[2], 1, 0, Mat(), r_hist, 1, bins, ranges);

  //顯示直方圖
  int hist_w = 512;
  int hist_h = 400;
  int bin_w = cvRound((double)hist_w/bins[0]);
  Mat histImage = Mat::zeros(hist_h, hist_w, CV_8UC3);

  //歸一化直方圖
  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 < bins[0]; 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("histImage", histImage);
}      
OpenCV + CPP 系列(十八)直方圖 與 直方圖均衡化

二維直方圖

源檔案 ​

​quick_demo.cpp​

​:實作類與公共函數

void QuickDemo::show_histogram2d_Demo(Mat& image) {
  Mat hsv, hs_hist;
  cvtColor(image, hsv, COLOR_BGR2HSV);

  int hbin = 30, sbin = 32;
  int hist_bins[] = { hbin , sbin };
  float h_range[] = { 0,180 };
  float s_range[] = { 0,256 };
  const float* hs_ranges[] = { h_range,s_range };
  int hs_channels[] = { 0,1 };
  calcHist(&hsv, 1, hs_channels, Mat(), hs_hist, 2, hist_bins, hs_ranges, true, false);

  double maxVal = 0;
  minMaxLoc(hs_hist, 0, &maxVal, 0, 0);
  int scale = 10;
  Mat hist_2d_image = Mat::zeros(sbin * scale, hbin * scale, CV_8UC3);
  for (int h = 0; h < hbin; h++) {
    for (int s = 0; s < sbin; s++) {
      float binVal = hs_hist.at<float>(h, s);
      int intensity = cvRound(binVal * 255 / maxVal);
      rectangle(hist_2d_image,
        Point(h * scale, s * scale),
        Point((h + 1) * scale, (s + 1) * scale),
        Scalar::all(intensity),
        -1
      );
    }
  }
  imshow("hist_2d_image0", hist_2d_image);
  applyColorMap(hist_2d_image, hist_2d_image, 2);
  imshow("hist_2d_image1", hist_2d_image);  
}      
OpenCV + CPP 系列(十八)直方圖 與 直方圖均衡化

三、直方圖均衡化

void QuickDemo::histogram_eq_Demo(Mat& image) {
    //灰階圖像直方圖均衡化
    Mat gray, dst;
    cvtColor(image, gray, COLOR_BGR2GRAY);
    equalizeHist(gray, dst);
    imshow("gray", gray);
    imshow("dst", dst);

    // 彩色圖像直方圖均衡化
    Mat hsv, hsv_dst;
    std::vector<Mat> hsv_split;
    cvtColor(image.clone(), hsv, COLOR_BGR2HSV);
    split(hsv, hsv_split);
    equalizeHist(hsv_split[2], hsv_split[2]);
    merge(hsv_split, hsv);
    cvtColor(hsv, hsv_dst, COLOR_HSV2BGR);
    imshow("hsv_dst", hsv_dst);
}      

繼續閱讀