设计一个界面,用来检测一幅图像的颜色分布,开发平台为Qt5.3.2+OpenCV2.4.9。
该程序的主要步骤如下:
1. 载入图像,选定一种颜色;
2. 设定阈值,在该值范围内判定像素属于预设的颜色;
3. 在界面的Label中输出结果。
首先,新建一个Qt Widgets Application,其中基类选择为QWidget,在创建完项目后,添加一个检测图像颜色的类ColorDetector。并在在Qt项目的.pro文件中添加:
INCLUDEPATH+=C:\OpenCV\install\include\opencvC:\OpenCV\install\include\opencv2C:\OpenCV\install\include
LIBS+=C:\OpenCV\lib\libopencv_calib3d249.dll.aC:\OpenCV\lib\libopencv_contrib249.dll.aC:\OpenCV\lib\libopencv_core249.dll.aC:\OpenCV\lib\libopencv_features2d249.dll.aC:\OpenCV\lib\libopencv_flann249.dll.aC:\OpenCV\lib\libopencv_gpu249.dll.aC:\OpenCV\lib\libopencv_highgui249.dll.aC:\OpenCV\lib\libopencv_imgproc249.dll.aC:\OpenCV\lib\libopencv_legacy249.dll.aC:\OpenCV\lib\libopencv_ml249.dll.aC:\OpenCV\lib\libopencv_nonfree249.dll.aC:\OpenCV\lib\libopencv_objdetect249.dll.aC:\OpenCV\lib\libopencv_ocl249.dll.aC:\OpenCV\lib\libopencv_video249.dll.aC:\OpenCV\lib\libopencv_photo249.dll.aC:\OpenCV\lib\libopencv_stitching249.dll.aC:\OpenCV\lib\libopencv_superres249.dll.aC:\OpenCV\lib\libopencv_ts249.aC:\OpenCV\lib\libopencv_videostab249.dll.a
进入图形界面文件widget.ui,在其中拖入三个按键,改名为”Open Image”,”Process”,”Color”,他们分别执行载入图像、颜色检测、颜色设定的操作。同时,拖入一个Vertical Slider,用于调整颜色的阈值。最后在下方设置一个Label,图像输出在该区域中。
设置各个按钮的objectName,分别为:
“Open Image”设定为”openImage”
“Process”设定为”dealImage”
“Color”设定为”colorButton”
“Vertical Slider”设定为”verticalSlider”
这是为了在程序中将信号与槽函数相对应:
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui -> setupUi(this);
connect(ui -> openImage, SIGNAL(clicked()), this, SLOT(openImage()));
connect(ui -> dealImage, SIGNAL(clicked()), this, SLOT(ImageProcess()));
connect(ui -> colorButton, SIGNAL(clicked()), this, SLOT(colorSelect()));
connect(ui -> verticalSlider, SIGNAL(valueChanged(int)), this, SLOT(changeDis(int)));
}
接着,定义处理图像所用的类,首先是colordetector.h:
#ifndef COLORDETECTOR_H_
#define COLORDETECTOR_H_
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <string>
class ColorDetector
{
private:
int minDist;
cv::Vec3b target;
cv::Mat result;
cv::Mat image;
ColorDetector();
static ColorDetector *singleton;
public:
static ColorDetector * getInstance();
static void destory();
void setColorDistanceThreshold(int);
int getColorDistanceThreshold() const;
void setTargetColor(unsigned char, unsigned char, unsigned char);
void setTargetColor(cv::Vec3b);
cv::Vec3b getTargetColor() const;
void process();
int getDistance(const cv::Vec3b&) const;
cv::Mat getResult() const;
bool setInputImage(std::string);
cv::Mat getInputImage() const;
};
#endif /* COLORDETECTOR_H_ */
接着在中添加colordetector.cpp:
#include "ColorDetector.h"
ColorDetector* ColorDetector::singleton = 0;
ColorDetector::ColorDetector():minDist(100)
{
target[0] = target[1] = target[2] = 0;
}
ColorDetector* ColorDetector::getInstance()
{
if(singleton == 0)
{
singleton = new ColorDetector;
}
return singleton;
}
void ColorDetector::destory()
{
if(singleton!=0)
{
delete singleton;
}
singleton = 0;
}
void ColorDetector::setColorDistanceThreshold(int distance)
{
if(distance < 0){
distance = 0;
}
minDist = distance;
}
int ColorDetector::getColorDistanceThreshold() const
{
return minDist;
}
void ColorDetector::setTargetColor(unsigned char red,
unsigned char green, unsigned char blue)
{
target[2] = red;
target[1] = green;
target[0] = blue;
}
void ColorDetector::setTargetColor(cv::Vec3b color)
{
target = color;
}
cv::Vec3b ColorDetector::getTargetColor() const
{
return target;
}
int ColorDetector::getDistance(const cv::Vec3b& color) const
{
return abs(color[0]-target[0])+abs(color[1]-target[1])+abs(color[2]-target[2]);
}
void ColorDetector::process()
{
result.create(image.rows, image.cols, CV_8U);
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(; it!=itend; ++it, ++itout)
{
if(getDistance(*it) < minDist)
{
*itout = 255;
}else{
*itout = 0;
}
}
}
cv::Mat ColorDetector::getResult() const
{
return result;
}
bool ColorDetector::setInputImage(std::string filename)
{
image = cv::imread(filename);
if(!image.data)
{
return false;
}
return true;
}
cv::Mat ColorDetector::getInputImage() const
{
return image;
}
接下来定义图形界面的处理函数,首先在widget.h中添加:
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QFileDialog>
#include <QImage>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "colordetector.h"
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
private:
Ui::Widget *ui;
QImage qimage;
cv::Mat image;
private slots:
void openImage();
void ImageProcess();
void colorSelect();
void changeDis(int);
};
#endif // WIDGET_H
接着在widget.cpp中定义信号与槽函数及相关操作:
#include "widget.h"
#include "ui_widget.h"
#include <QColorDialog>
#include <QDebug>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui -> setupUi(this);
connect(ui -> openImage, SIGNAL(clicked()), this, SLOT(openImage()));
connect(ui -> dealImage, SIGNAL(clicked()), this, SLOT(ImageProcess()));
connect(ui -> colorButton, SIGNAL(clicked()), this, SLOT(colorSelect()));
connect(ui -> verticalSlider, SIGNAL(valueChanged(int)), this, SLOT(changeDis(int)));
}
Widget::~Widget()
{
delete ui;
}
void Widget::openImage()
{
QString fileName = QFileDialog::getOpenFileName(this,
tr("Open Image"), ".",
tr("Image Files (*.png *.jpg *.jpeg *.bmp)"));
ColorDetector::getInstance()->setInputImage(fileName.toLatin1().data());
cv::Mat input;
input = ColorDetector::getInstance()->getInputImage();
if (!input.data)
{
ui->dealImage->setEnabled(false);
ui->colorButton->setEnabled(false);
ui->verticalSlider->setEnabled(false);
qDebug() << "No Input Image";
}
else
{
ui->dealImage->setEnabled(true);
ui->colorButton->setEnabled(true);
ui->verticalSlider->setEnabled(true);
cv::namedWindow("image");
cv::imshow("image",ColorDetector::getInstance()->getInputImage());
ImageProcess();
}
}
void Widget::ImageProcess()
{
ColorDetector::getInstance()->process();
cv::cvtColor(ColorDetector::getInstance()->getResult(),image,CV_GRAY2RGB);
if (!image.data)
qDebug() << "error!";
qimage = QImage((const unsigned char*)(image.data),image.cols,image.rows,QImage::Format_RGB888);
ui->label->setPixmap(QPixmap::fromImage(qimage).scaledToHeight(300));
//ui->label->resize(ui->label->pixmap()->size());
}
void Widget::colorSelect()
{
QColor color = QColorDialog::getColor(Qt::green,this);
if(color.isValid())
{
ColorDetector::getInstance()->setTargetColor(
color.red(),color.green(),color.blue());
}
//ImageProcess();
}
void Widget::changeDis(int value)
{
ColorDetector::getInstance()->setColorDistanceThreshold(value);
//ImageProcess();
}
效果如下,未输入图像时,图像处理、颜色选择按钮部分不可操作:
原文地址:http://blog.csdn.net/liyuefeilong/article/details/43955735