先设计一个简单的二值化的程序:
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
class ColorDetector {
private:
// minimum acceptable distance
int minDist;
// target color
cv::Vec3b target;
// image containing resulting binary map
cv::Mat result;
public:
// empty constructor
ColorDetector() : minDist(100) {
// default parameter initialization here
target[0]= target[1]= target[2]= 0;
}
// Getters and setters
// Sets the color distance threshold.
// Threshold must be positive, otherwise distance threshold
// is set to 0.
void setColorDistanceThreshold(int distance) {
if (distance<0)
distance=0;
minDist= distance;
}
// Gets the color distance threshold
int getColorDistanceThreshold() const {
return minDist;
}
// Sets the color to be detected
void setTargetColor(unsigned char red, unsigned char green, unsigned char blue) {
target[2]= red;
target[1]= green;
target[0]= blue;
}
// Sets the color to be detected
void setTargetColor(cv::Vec3b color) {
target= color;
}
int getDistance(const cv::Vec3b& color) const {
return abs(color[0]-target[0])+
abs(color[1]-target[1])+
abs(color[2]-target[2]);
}
cv::Mat ColorDetector::process(const cv::Mat &image) {
// re-allocate binary map if necessary
// same size as input image, but 1-channel
result.create(image.rows,image.cols,CV_8U);
// get the iterators
cv::Mat_<cv::Vec3b>::const_iterator it= image.begin<cv::Vec3b>();
cv::Mat_<cv::Vec3b>::const_iterator itend= image.end<cv::Vec3b>();
cv::Mat_<uchar>::iterator itout= result.begin<uchar>();
// for each pixel
for ( ; it!= itend; ++it, ++itout) {
// process each pixel ---------------------
// compute distance from target color
if (getDistance(*it)<minDist) {
*itout= 255;
} else {
*itout= 0;
}
// end of pixel processing ----------------
}
return result;
}
};
int main()
{
// 1. Create image processor object
ColorDetector cdetect;
// 2. Read input image
cv::Mat image=cv::imread("boldt.jpg");
if (!image.data)
return 0;
// 3. Set input parameters
cdetect.setTargetColor(130,190,230);//here blue sky
cv::namedWindow("result");
// 4. Process the image and display the result
cv::imshow("result",cdetect.process(image));
cv::waitKey();
return 0;
}
效果:
接下来。。。。。
策略设计模式就是将算法封装在类中,比如我们见到的进行一个二值化算法;
算法的核心,将像素的颜色与目标颜色比较 ,表示:
// get the iterators
cv::Mat_<cv::Vec3b>::const_iterator it=
image.begin<cv::Vec3b>();
cv::Mat_<cv::Vec3b>::const_iterator itend=
image.end<cv::Vec3b>();
cv::Mat_<uchar>::iterator itout=
Result.begin<uchar>();
//for each pixel
for ( ; it!= itend; ++it, ++itout) {
// process each pixel -----------------------
// compute distance from target color
if (getDistance(*it)<minDist) {
*itout= 255;
} else {
*itout= 0;
}
// end of pixel processiong -----------------
如何度量颜色距离:
int getDistance(const cv::Vec3b& color) const {
return abs(color[0]-target[0])+
abs(color[1]-target[1])+
abs(color[2]-target[2]);
在ui中拖两个按钮和一个标签,
然后再mainwindow里面添加如下代码:
void MainWindow::on_pushButton_clicked()
{
QString fileName = QFileDialog::getOpenFileName(this,
tr("Open Image"),".",
tr("Image File (*.png *.jpg *.jpeg *.bmp)"));
std::string filename= fileName.toLatin1().data();
ColorDetectController::getInstance()->setInputImage(filename);
// cv::imshow("Input Image", ColorDetectController::getInstance()->getInputImage());
// qimage= ColorDetectController::getInstance()->getInputImage();
cv::cvtColor(ColorDetectController::getInstance()->getInputImage(),qimage,CV_BGR2RGB);
// Qt image
QImage img= QImage((const unsigned char*)(qimage.data),
qimage.cols,qimage.rows,QImage::Format_RGB888);
// display on label
ui->label->setPixmap(QPixmap::fromImage(img));
// resize the label to fit the image
ui->label->resize(ui->label->pixmap()->size());
}
void MainWindow::on_pushButton_2_clicked()
{
// target color is hard-coded here
ColorDetectController::getInstance()->setTargetColor(130,190,230);
// process the input imagr and display result
ColorDetectController::getInstance()->process();
// cv::imshow("Output Result", ColorDetectController::getInstance()->getLastResult());
// cv::cvtColor(ColorDetectController::getInstance()->getLastResult(),qimage,CV_BGR2RGB);
qimage= ColorDetectController::getInstance()->getLastResult();
// Qt image
QImage img= QImage((const unsigned char*)(qimage.data),
qimage.cols,qimage.rows,QImage::Format_Indexed8);
// display on label
ui->label->setPixmap(QPixmap::fromImage(img));
// resize the label to fit the image
ui->label->resize(ui->label->pixmap()->size());
}
如图:
最终运行代码:
并附上部分代码:
colodetectcontroller头文件:
#ifndef COLORDETECTCONTROLLER_H
#define COLORDETECTCONTROLLER_H
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
class ColorDetector {
private:
// minimum acceptable distance
int minDist;
// target color
cv::Vec3b target;
// image containing Resulting binary map
cv::Mat Result;
public:
// empty constructor
ColorDetector() : minDist(100) {
// default parameter initialization here
target[0]= target[1]= target[2]= 0;
}
// Sets the color distance threshold.
// Threshold must be positive,
// otherwise distance threshold is set to 0.
void setColorDistanceThreshold(int distance) {
if (distance<0)
distance=0;
minDist= distance;
}
// Get the color distance threshold
int getColorDistanceThreshold() const {
return minDist;
}
// Sets the color to be detected
void setTargetColor(unsigned char red,
unsigned char green,
unsigned char blue) {
// BGR order
target[2]= red;
target[1]= green;
target[0]= blue;
}
// Sets the color to be detected
void setTargetColor(cv::Vec3b color) {
target= color;
}
// Gets the color to be detected
cv::Vec3b getTargetColor() const {
return target;
}
int getDistance(const cv::Vec3b& color) const {
return abs(color[0]-target[0])+
abs(color[1]-target[1])+
abs(color[2]-target[2]);
}
cv::Mat ColorDetector::process(const cv::Mat &image) {
// re-allocate binary map if necessary
// same size as input image, but 1-channel
Result.create(image.rows,image.cols,CV_8U);
// get the iterators
cv::Mat_<cv::Vec3b>::const_iterator it=
image.begin<cv::Vec3b>();
cv::Mat_<cv::Vec3b>::const_iterator itend=
image.end<cv::Vec3b>();
cv::Mat_<uchar>::iterator itout=
Result.begin<uchar>();
//for each pixel
for ( ; it!= itend; ++it, ++itout) {
// process each pixel -----------------------
// compute distance from target color
if (getDistance(*it)<minDist) {
*itout= 255;
} else {
*itout= 0;
}
// end of pixel processiong -----------------
}
return Result;
}
};
class ColorDetectController {
private:
// the algorithm class
ColorDetector *cdetect;
cv::Mat image; // The image to be processed
cv::Mat Result; // The image Result
// pointer to the singleton
static ColorDetectController *singleton;
// private constructor
ColorDetectController() {
// setting up the application
cdetect= new ColorDetector();
}
public:
// Get sccess to Singleton instance
static ColorDetectController *getInstance() {
//Creates the instance at first call
if (singleton == 0)
singleton= new ColorDetectController;
return singleton;
}
//Release the singleton instance of this controller
static void destroy() {
if (singleton != 0) {
delete singleton;
singleton= 0;
}
}
// Set the color distance threshold
void setColorDestanceThreshold(int distance) {
cdetect->setColorDistanceThreshold(distance);
}
// Get the color distance threshold
int getColorDistanceThreshold() const {
return cdetect->getColorDistanceThreshold();
}
//Set the color to be detected
void setTargetColor(unsigned char red,
unsigned char green,unsigned char blue) {
cdetect->setTargetColor(red,green,blue);
}
// Get the color to be detected
void getTargetColor(unsigned char &red,
unsigned char &green,unsigned char &blue) const {
cv::Vec3b color= cdetect->getTargetColor();
red= color[2];
green= color[1];
blue= color[0];
}
// Set the input image. Reads it fram file.
bool setInputImage(std::string filename) {
image= cv::imread(filename);
if (!image.data)
return false;
else
return true;
}
// Return the current input image.
const cv::Mat getInputImage() const {
return image;
}
// Perform image procesing.
void process() {
Result= cdetect->process(image);
}
// Return the image Result from the latest processing.
const cv::Mat getLastResult() const {
return Result;
}
// Detects processor objects created by the controller.
~ColorDetectController() {
delete cdetect;
}
};
#endif // COLORDETECTCONTROLLER_H
差不多就这些。。。折腾了好一会。。