码迷,mamicode.com
首页 > 其他好文 > 详细

OpenCV2学习笔记(六):检测图像颜色小程序

时间:2015-02-26 20:23:12      阅读:547      评论:0      收藏:0      [点我收藏+]

标签:qt   opencv   阈值分割   c++   图像处理   

设计一个界面,用来检测一幅图像的颜色分布,开发平台为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();
}

效果如下,未输入图像时,图像处理、颜色选择按钮部分不可操作:

技术分享

技术分享

技术分享

OpenCV2学习笔记(六):检测图像颜色小程序

标签:qt   opencv   阈值分割   c++   图像处理   

原文地址:http://blog.csdn.net/liyuefeilong/article/details/43955735

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!