##檢測圖像顏色小程序
設計一個界面,用來檢測一幅圖像的顏色分布,開發平臺為Qt5.3.2+OpenCV2.4.9。
該程序的主要步驟如下:?
1\. 載入圖像,選定一種顏色;?
2\. 設定閾值,在該值范圍內判定像素屬于預設的顏色;?
3\. 在界面的Label中輸出結果。
首先,新建一個Qt Widgets Application,其中基類選擇為QWidget,在創建完項目后,添加一個檢測圖像顏色的類ColorDetector。并在在Qt項目的.pro文件中添加:
~~~
INCLUDEPATH+=C:\OpenCV\install\include\opencv\
C:\OpenCV\install\include\opencv2\
C:\OpenCV\install\include
LIBS+=C:\OpenCV\lib\libopencv_calib3d249.dll.a\
C:\OpenCV\lib\libopencv_contrib249.dll.a\
C:\OpenCV\lib\libopencv_core249.dll.a\
C:\OpenCV\lib\libopencv_features2d249.dll.a\
C:\OpenCV\lib\libopencv_flann249.dll.a\
C:\OpenCV\lib\libopencv_gpu249.dll.a\
C:\OpenCV\lib\libopencv_highgui249.dll.a\
C:\OpenCV\lib\libopencv_imgproc249.dll.a\
C:\OpenCV\lib\libopencv_legacy249.dll.a\
C:\OpenCV\lib\libopencv_ml249.dll.a\
C:\OpenCV\lib\libopencv_nonfree249.dll.a\
C:\OpenCV\lib\libopencv_objdetect249.dll.a\
C:\OpenCV\lib\libopencv_ocl249.dll.a\
C:\OpenCV\lib\libopencv_video249.dll.a\
C:\OpenCV\lib\libopencv_photo249.dll.a\
C:\OpenCV\lib\libopencv_stitching249.dll.a\
C:\OpenCV\lib\libopencv_superres249.dll.a\
C:\OpenCV\lib\libopencv_ts249.a\
C:\OpenCV\lib\libopencv_videostab249.dll.a
~~~
進入圖形界面文件widget.ui,在其中拖入三個按鍵,改名為”Open Image”,”Process”,”Color”,他們分別執行載入圖像、顏色檢測、顏色設定的操作。同時,拖入一個Vertical Slider,用于調整顏色的閾值。最后在下方設置一個Label,圖像輸出在該區域中。

設置各個按鈕的objectName,分別為:?
“Open Image”設定為”openImage”?
“Color”設定為”colorButton”?
“Process”設定為”ImageProcess”?
“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 -> ImageProcess, SIGNAL(clicked()), this, SLOT(ImageProcess()));
connect(ui -> colorButton, SIGNAL(clicked()), this, SLOT(colorSelect()));
connect(ui -> verticalSlider, SIGNAL(valueChanged(int)), this, SLOT(changeDis(int)));
}
~~~
這里規定當未有輸入圖像時,圖像處理按鈕不可用,在以上的Widget構造函數中添加:
~~~
// 在未輸入圖像時,屏蔽圖像處理的按鈕
ui -> ImageProcess -> setEnabled(false);
ui -> colorButton -> setEnabled(false);
ui -> verticalSlider -> setEnabled(false);
~~~
接著,定義處理圖像所用的類,首先是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();
// 提供靜態的接口來獲得ColorDetector對象
static ColorDetector *singleton;
public:
cv::Mat getInputImage() const; // 載入圖像
cv::Mat getResult() const; // 返回圖像處理結果
void process(); // 將閾值范圍內的像素點置為255,其余為0
int getDistance(const cv::Vec3b&) const;
bool setInputImage(std::string); // 判斷是否已輸入圖像
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;
};
#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 -> ImageProcess, SIGNAL(clicked()), this, SLOT(ImageProcess()));
connect(ui -> colorButton, SIGNAL(clicked()), this, SLOT(colorSelect()));
connect(ui -> verticalSlider, SIGNAL(valueChanged(int)), this, SLOT(changeDistance(int)));
// 在未輸入圖像時,屏蔽圖像處理的按鈕
ui -> ImageProcess -> setEnabled(false);
ui -> colorButton -> setEnabled(false);
ui -> verticalSlider -> setEnabled(false);
}
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)
{
qDebug() << "No Input Image";
}
else
{
// 當檢測到輸入圖像,可激活圖像處理按鍵,并顯示原圖像
ui->ImageProcess->setEnabled(true);
ui->colorButton->setEnabled(true);
ui->verticalSlider->setEnabled(true);
cv::namedWindow("image");
cv::imshow("image",ColorDetector::getInstance()->getInputImage());
}
}
void Widget::ImageProcess()
{
ColorDetector::getInstance()->process();
cv::cvtColor(ColorDetector::getInstance()->getResult(),image,CV_GRAY2RGB);
qimage = QImage((const unsigned char*)(image.data),image.cols,image.rows,QImage::Format_RGB888);
ui->label->setPixmap(QPixmap::fromImage(qimage).scaledToHeight(300));
}
void Widget::colorSelect()
{
QColor color = QColorDialog::getColor(Qt::green,this);
if(color.isValid())
{
ColorDetector::getInstance()->setTargetColor(
color.red(),color.green(),color.blue());
}
}
void Widget::changeDistance(int value)
{
ColorDetector::getInstance()->setColorDistanceThreshold(value);
}
~~~
效果如下,未輸入圖像時,圖像處理、顏色選擇按鈕部分不可操作:
1.未輸入圖像時:

2.載入圖像后:

3.打開color按鈕,可選擇要檢測的顏色:

4.選定顏色后,拖動可調節閾值,點擊Process可輸出檢測結果。

- 前言
- Win8.1下OpenCV2.4.9+Qt5.3.2開發環境搭建
- OpenCV2學習筆記(一)
- OpenCV2學習筆記(二)
- OpenCV2學習筆記(三)
- OpenCV2學習筆記(四)
- OpenCV2學習筆記(五)
- OpenCV2學習筆記(六)
- OpenCV2學習筆記(七)
- OpenCV2學習筆記(八)
- OpenCV2學習筆記(九)
- OpenCV2學習筆記(十)
- OpenCV2學習筆記(十一)
- OpenCV2學習筆記(十二)
- OpenCV2學習筆記(十三)
- OpenCV2學習筆記(十四)
- OpenCV2學習筆記(十五)
- OpenCV2學習筆記(十六)
- OpenCV2學習筆記(十七)
- OpenCV2學習筆記(十八)
- OpenCV2學習筆記(十九)
- OpenCV2學習筆記(二十)
- OpenCV2學習筆記(二十一)
- OpenCV2學習筆記(二十二)