Opencv直方图反投影检测颜色
2017-10-03 15:25
267 查看
本文按照OpenCV2计算机视觉编程手册书写代码。
对于书中一些地方,为了实现更好的效果有改动。
首先是第一个类ColorHistogram:
第二个类ContentFinder:
主程序(main):
书中的
并没有设置修改方法,这里设置了
这一方法用于修改bin值,一举解决了按照书上代码有时无法显示图像的问题。
另外,通过滑动条可以动态调整识别阈值。
对于书中一些地方,为了实现更好的效果有改动。
首先是第一个类ColorHistogram:
#pragma once #if !defined COLHISTOGRAM #define COLHISTOGRAM #include <opencv2\core\core.hpp> #include <opencv2\imgproc\imgproc.hpp> class ColorHistogram { private: int histSize[3]; float hranges[2]; const float* ranges[3]; int channels[3]; public: ColorHistogram() { histSize[0] = histSize[1] = histSize[2] = 256; hranges[0] = 0.0; hranges[1] = 256.0; ranges[0] = hranges; ranges[1] = hranges; ranges[2] = hranges; channels[0] = 0; channels[1] = 1; channels[2] = 2; } void setSize(int size) { histSize[0] = histSize[1] = histSize[2] = size; } cv::Mat getHistogram(const cv::Mat &image) { cv::Mat hist; hranges[0] = 0.0; hranges[1] = 256.0; channels[0] = 0; channels[1] = 1; channels[2] = 2; 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); hranges[0] = 0.0; hranges[1] = 256.0; channels[0] = 0; channels[1] = 1; channels[2] = 2; cv::calcHist(&image, 1, channels, cv::Mat(), hist, 3, histSize, ranges ); return hist; } cv::Mat getHueHistogram(const cv::Mat &image, int minSaturation = 0) { cv::Mat hist; cv::Mat hsv; cv::cvtColor(image, hsv, CV_BGR2HSV); cv::Mat mask; if (minSaturation>0) { std::vector<cv::Mat> v; cv::split(hsv, v); cv::threshold(v[1], mask, minSaturation, 255, cv::THRESH_BINARY); } hranges[0] = 0.0; hranges[1] = 180.0; channels[0] = 0; cv::calcHist(&hsv, 1, channels, mask, hist, 1, histSize, ranges ); return hist; } // Computes the 2D ab histogram. // BGR source image is converted to Lab cv::Mat getabHistogram(const cv::Mat &image) { cv::Mat hist; // Convert to Lab color space cv::Mat lab; cv::cvtColor(image, lab, CV_BGR2Lab); // Prepare arguments for a 2D color histogram hranges[0] = 0; hranges[1] = 256.0; channels[0] = 1; // the two channels used are ab channels[1] = 2; // Compute histogram cv::calcHist(&lab, 1, // histogram of 1 image only channels, // the channel used cv::Mat(), // no mask is used hist, // the resulting histogram 2, // it is a 2D histogram histSize, // number of bins ranges // pixel value range ); return hist; } }; #endif
第二个类ContentFinder:
#pragma once #if !defined OFINDER #define OFINDER #include <opencv2\core\core.hpp> #include <opencv2\imgproc\imgproc.hpp> class ContentFinder { private: // histogram parameters float hranges[2]; const float* ranges[3]; int channels[3]; float threshold; // decision threshold cv::Mat histogram; // histogram can be sparse 输入直方图 cv::SparseMat shistogram; // or not bool isSparse; public: ContentFinder() : threshold(0.1f), isSparse(false) { // in this class, // all channels have the same range ranges[0] = hranges; ranges[1] = hranges; ranges[2] = hranges; 4000 } // Sets the threshold on histogram values [0,1] void setThreshold(float t) { threshold = t; } // Gets the threshold float getThreshold() { return threshold; } // Sets the reference histogram void setHistogram(const cv::Mat& h) { isSparse = false; cv::normalize(h, histogram, 1.0); } // Sets the reference histogram void setHistogram(const cv::SparseMat& h) { isSparse = true; cv::normalize(h, shistogram, 1.0, cv::NORM_L2); } // All channels used, with range [0,256] cv::Mat find(const cv::Mat& image) { cv::Mat result; hranges[0] = 0.0; // default range [0,256] hranges[1] = 256.0; channels[0] = 0; // the three channels channels[1] = 1; channels[2] = 2; return find(image, hranges[0], hranges[1], channels); } // Finds the pixels belonging to the histogram cv::Mat find(const cv::Mat& image, float minValue, float maxValue, int *channels) { cv::Mat result; hranges[0] = minValue; hranges[1] = maxValue; if (isSparse) { // call the right function based on histogram type for (int i = 0; i<shistogram.dims(); i++) this->channels[i] = channels[i]; cv::calcBackProject(&image, 1, // we only use one image at a time channels, // vector specifying what histogram dimensions belong to what image channels shistogram, // the histogram we are using result, // the resulting back projection image ranges, // the range of values, for each dimension 255.0 // the scaling factor is chosen such that a histogram value of 1 maps to 255 ); } else { for (int i = 0; i<histogram.dims; i++) this->channels[i] = channels[i]; //某对象的this指针,指向被调用函数所在的对象,此处对象为ContentFinder类 //this->channels[i]即ContentFinder类的私有成员channels[3] //对ContentFinder类各成员的访问均通过this进行 cv::calcBackProject(&image, 1, // we only use one image at a time channels, // 向量表示哪个直方图维度属于哪个图像通道 histogram, // 用到的直方图 result, // 反向投影的图像 ranges, // 每个维度值的范围 255.0 // 选用的换算系数 ); } // Threshold back projection to obtain a binary image阈值分割反向投影图像得到二值图 if (threshold>0.0)// 设置的阈值>0时,才进行阈值分割 cv::threshold(result, result, 255.0*threshold, 255.0, cv::THRESH_BINARY); return result; } }; #endif
主程序(main):
#include <cv.h> #include <highgui.h> #include <opencv2\opencv.hpp> #include "ColorHistogram.h" #include "ContentFinder.h" using namespace std; using namespace cv; /// 全局变量的声明与初始化 const int alpha_slider_max = 99; int alpha_slider; cv::Mat image; cv::Mat imageROI; ContentFinder finder; cv::Mat result1; ColorHistogram hc; VideoCapture cap(1); Mat color; void on_trackbar(int, void*) { float a = float(alpha_slider / 100.0); finder.setThreshold(a); while (true) { cap >> color; namedWindow("1"); imshow("1", color); result1 = finder.find(color); Mat res; Mat element5(3, 3, CV_8U, Scalar(1)); morphologyEx(result1, res, MORPH_CLOSE, element5); blur(res, res, Size(2, 2)); cv::namedWindow("Color Detection Result"); cv::imshow("Color Detection Result", res); char c = waitKey(33); if (c == 27) break; } return; } int main(int argc, char** argv) { image = cv::imread("E:\\ProgramProject\\1.png"); if (!image.data) return 0; //cv::Mat imageROI; imageROI = image(cv::Rect(0, 0, 30, 24)); hc.setSize(4); cv::Mat shist = hc.getHistogram(imageROI); finder.setHistogram(shist); /// 初始化为零 alpha_slider = 9; /// 创建窗体 namedWindow("Rate"); /// 在创建的窗体中创建一个滑动条控件 char TrackbarName[50]; sprintf(TrackbarName, "Alpha x %d", alpha_slider); createTrackbar(TrackbarName, "Rate", &alpha_slider, alpha_slider_max, on_trackbar); /// 结果在回调函数中显示 on_trackbar(alpha_slider, 0); return 0; }
书中的
histSize[0] = histSize[1] = histSize[2] = 256;
并没有设置修改方法,这里设置了
void setSize(int size) { histSize[0] = histSize[1] = histSize[2] = size; }
这一方法用于修改bin值,一举解决了按照书上代码有时无法显示图像的问题。
另外,通过滑动条可以动态调整识别阈值。
相关文章推荐
- opencv2 反向投影直方图检测特定图像内容
- OpenCV_颜色直方图的计算、显示、处理、对比及反向投影
- OpenCV之彩色直方图反向投影(图像相似性检测)
- OpenCV【5】---通过反投影直方图以检测特定的图像内容
- opencv2对读书笔记——反投影直方图以检测待定的图像内容
- OpenCV之灰度直方图反向投影(图像相似性检测)
- OpenCV_颜色直方图的计算、显示、处理、对比及反向投影
- OpenCV2编程手册笔记之 4.5反投影直方图以检测特定图像内容
- OpenCV之彩色直方图反向投影(图像相似性检测)
- OpenCV—反向投影直方图检测特定图像内容
- opencv2反投影直方图以检测特定的图像内容
- OpenCV之灰度直方图反向投影(图像相似性检测)
- OpenCV_颜色直方图的计算、显示、处理、对比及反向投影【转】
- opencv2在直方图反投影算法中使用颜色信息
- OPENCV直方图计算原理及反向投影检测原理
- OPENCV直方图计算原理及反向投影检测原理
- OpenCV_颜色直方图的计算、显示、处理、对比及反向投影
- 使用Opencv进行轮廓检测,字符提取,简单的直方图字符识别!
- OpenCV2马拉松第11圈——meanshift与直方图反向投影