1Dとカラーのやつは「OpenCV 2 Computer Vision Application Programming Cookbook」に載っているやつ。これを基に、2次元ヒストグラム画像作成など自分なりに手を入れているけれど、まだ中途半端。
#include <opencv2/opencv.hpp> class Histogram1D { private: int histSize[1]; float hranges[2]; const float* ranges[1]; int channels[1]; public: Histogram1D(int hsize = 256) { histSize[0] = hsize; //number of bins hranges[0] = 0.0; //min pixel value hranges[1] = 255.0; //max pixel value ranges[0] = hranges; channels[0] = 0; //by default, we lookup channel 0 } void setHistSize(int hsize) { histSize[0] = hsize; } void setRanges(float min, float max) { hranges[0] = min; hranges[1] = max; ranges[0] = hranges; if(max-min<histSize[0]) { histSize[0] = (int)(max-min); } } cv::MatND getHistogram(const cv::Mat &image, int ch = 0) { cv::MatND hist; channels[0] = ch; cv::calcHist(&image, 1, channels, cv::Mat(), hist, 1, histSize, ranges); return hist; } cv::Mat getHistogramImage(const cv::Mat &image, int channel = 0) { cv::MatND hist= getHistogram(image, channel); double maxVal = 0; double minVal = 0; cv::minMaxLoc(hist, &minVal, &maxVal, 0, 0); cv::Mat histImg(histSize[0], histSize[0], CV_8U, cv::Scalar(255)); int hpt = static_cast<int>(0.9*histSize[0]); for(int h=0; h<histSize[0]; h++) { float binVal = hist.at<float>(h); int intensity = static_cast<int>(binVal*hpt/maxVal); cv::line(histImg, cv::Point(h,histSize[0]), cv::Point(h,histSize[0]-intensity), cv::Scalar::all(0)); } return histImg; } }; class Histogram2D { private: int histSize[2]; float hranges[2]; const float* ranges[2]; int channels[2]; public: Histogram2D(int h1size=256, int h2size = 256) { histSize[0] = h1size; histSize[1] = h2size; hranges[0] = 0.0; hranges[1] = 255.0; ranges[0] = hranges; ranges[1] = hranges; channels[0] = 0; channels[1] = 1; } cv::MatND getHistogram(const cv::Mat &img1, const cv::Mat &img2) { cv::Mat planes[2]; img1.copyTo(planes[0]); img2.copyTo(planes[1]); cv::MatND hist; cv::calcHist(planes, 2, channels, cv::Mat(), hist, 2, histSize, ranges); return hist; } cv::Mat getHistogramImage(const cv::Mat &img1, const cv::Mat &img2) { cv::MatND hist= getHistogram(img1, img2); double maxVal = 0; double minVal = 0; cv::minMaxLoc(hist, &minVal, &maxVal, 0, 0); cv::Mat histImg(histSize[0], histSize[1], CV_8U, cv::Scalar(0)); for(int h=0; h<histSize[0]; h++) { for(int i=0; i<histSize[1]; i++) { float binVal = hist.at<float>(h,i); uchar intensity = static_cast<uchar>(binVal*255/maxVal); histImg.at<uchar>(h,i) = intensity; } } return histImg; } }; class ColorHistogram { private: int histSize[3]; float hranges[2]; const float* ranges[3]; int channels[3]; public: ColorHistogram(int hSize = 256) { histSize[0] = histSize[1] = histSize[2] = hSize; hranges[0] = 0.0; hranges[1] = 255.0; ranges[0] = hranges; ranges[1] = hranges; ranges[2] = hranges; channels[0] = 0; channels[1] = 1; channels[2] = 2; } cv::MatND getHistogram(const cv::Mat &image) { cv::MatND hist; cv::calcHist(&image, 1, channels, cv::Mat(), hist, 3, histSize, ranges); return hist; } cv::SparseMat getSparseHistogram(const cv::Mat &image) { cv::SparseMat hist(3, histSize, CV_32F); cv::calcHist(&image, 1, channels, cv::Mat(), hist, 3, histSize, ranges); return hist; } };
呼び出す側のソース例。
#include <opencv2/opencv.hpp> #include "histogram.hpp" #ifdef _DEBUG #pragma comment(lib,"opencv_core230d.lib") #pragma comment(lib,"opencv_highgui230d.lib") #pragma comment(lib,"opencv_imgproc230d.lib") #else #pragma comment(lib,"opencv_core230.lib") #pragma comment(lib,"opencv_highgui230d.lib") #pragma comment(lib,"opencv_imgproc230d.lib") #endif using namespace cv; using std::cout; using std::endl; int main() { //モノクロ画像のヒストグラム表示 Mat gray_img = imread("d:/test1.bmp", 0); imshow("gray", gray_img); Histogram1D h1(256); imshow("Histogram", h1.getHistogramImage(gray_img)); //カラー画像のチャネル別ヒストグラム画像表示j Mat cimg = imread("d:/test2.bmp"); imshow("color", cimg); imshow("B", h1.getHistogramImage(cimg)); imshow("G", h1.getHistogramImage(cimg, 1)); imshow("R", h1.getHistogramImage(cimg, 2)); Mat hsvImg; cvtColor(cimg, hsvImg, CV_BGR2HSV_FULL); imshow("H", h1.getHistogramImage(hsvImg, 0)); imshow("S", h1.getHistogramImage(hsvImg, 1)); imshow("V", h1.getHistogramImage(hsvImg, 2)); //h1.setRanges(0.0, 180.0); //imshow("H", h1.getHistogramImage(hsvImg)); //2チャンネル2次元ヒストグラム画像表示 std::vector<cv::Mat> planes; cv::split(cimg, planes); Histogram2D h2(128,128); imshow("2Dhist", h2.getHistogramImage(planes[0], planes[1])); //各ヒストグラムを得る。 MatND hist1 = h1.getHistogram(gray_img); MatND hist2 = h2.getHistogram(planes[0], planes[1]); //cout << hist2 << endl; waitKey(); }
0 件のコメント:
コメントを投稿