array(2) { ["docs"]=> array(10) { [0]=> array(10) { ["id"]=> string(3) "428" ["text"]=> string(77) "Visual Studio 2017 单独启动MSDN帮助(Microsoft Help Viewer)的方法" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(8) "DonetRen" ["tagsname"]=> string(55) "Visual Studio 2017|MSDN帮助|C#程序|.NET|Help Viewer" ["tagsid"]=> string(23) "[401,402,403,"300",404]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400964" ["_id"]=> string(3) "428" } [1]=> array(10) { ["id"]=> string(3) "427" ["text"]=> string(42) "npm -v;报错 cannot find module "wrapp"" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "zzty" ["tagsname"]=> string(50) "node.js|npm|cannot find module "wrapp“|node" ["tagsid"]=> string(19) "[398,"239",399,400]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400760" ["_id"]=> string(3) "427" } [2]=> array(10) { ["id"]=> string(3) "426" ["text"]=> string(54) "说说css中pt、px、em、rem都扮演了什么角色" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(12) "zhengqiaoyin" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400640" ["_id"]=> string(3) "426" } [3]=> array(10) { ["id"]=> string(3) "425" ["text"]=> string(83) "深入学习JS执行--创建执行上下文(变量对象,作用域链,this)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "Ry-yuan" ["tagsname"]=> string(33) "Javascript|Javascript执行过程" ["tagsid"]=> string(13) "["169","191"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511399901" ["_id"]=> string(3) "425" } [4]=> array(10) { ["id"]=> string(3) "424" ["text"]=> string(30) "C# 排序技术研究与对比" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "vveiliang" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(8) ".Net Dev" ["catesid"]=> string(5) "[199]" ["createtime"]=> string(10) "1511399150" ["_id"]=> string(3) "424" } [5]=> array(10) { ["id"]=> string(3) "423" ["text"]=> string(72) "【算法】小白的算法笔记:快速排序算法的编码和优化" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "penghuwan" ["tagsname"]=> string(6) "算法" ["tagsid"]=> string(7) "["344"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511398109" ["_id"]=> string(3) "423" } [6]=> array(10) { ["id"]=> string(3) "422" ["text"]=> string(64) "JavaScript数据可视化编程学习(二)Flotr2,雷达图" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "chengxs" ["tagsname"]=> string(28) "数据可视化|前端学习" ["tagsid"]=> string(9) "[396,397]" ["catesname"]=> string(18) "前端基本知识" ["catesid"]=> string(5) "[198]" ["createtime"]=> string(10) "1511397800" ["_id"]=> string(3) "422" } [7]=> array(10) { ["id"]=> string(3) "421" ["text"]=> string(36) "C#表达式目录树(Expression)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "wwym" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(4) ".NET" ["catesid"]=> string(7) "["119"]" ["createtime"]=> string(10) "1511397474" ["_id"]=> string(3) "421" } [8]=> array(10) { ["id"]=> string(3) "420" ["text"]=> string(47) "数据结构 队列_队列实例:事件处理" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "idreamo" ["tagsname"]=> string(40) "C语言|数据结构|队列|事件处理" ["tagsid"]=> string(23) "["246","247","248",395]" ["catesname"]=> string(12) "数据结构" ["catesid"]=> string(7) "["133"]" ["createtime"]=> string(10) "1511397279" ["_id"]=> string(3) "420" } [9]=> array(10) { ["id"]=> string(3) "419" ["text"]=> string(47) "久等了,博客园官方Android客户端发布" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(3) "cmt" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511396549" ["_id"]=> string(3) "419" } } ["count"]=> int(200) } 222 OpenCV2 颜色识别 - 爱码网
xianglan

在这个例子中,我们开始选定一种颜色,并设置一个阈值

然后把图片中和所选颜色的差别在阈值中的点标定出来

在这个例子中,主要要注意这两点:

1. OpenCV与QT的结合,包括Mat 与 QImage 的转换

2. 我们使用了类来实现此功能,创建了一个单例模式的类

首先我们创建一个简单的图形界面,使用的是QT

创建处理图像用的类

#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_ */

将其构造函数声明为private,提供静态的接口来获得ColorDetector对象

void setColorDistanceThreshold(int) 用于设置阈值
void setTargetColor(unsigned char, unsigned char, unsigned char)
void setTargetColor(cv::Vec3b) 用于设置颜色
bool setInputImage(std::string) 用于载入待处理图像
cv::Mat getResult() const 用于返回处理结果,结果用一副图像表示

其具体实现如下

#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;
}

在前面文章中,讲了遍历像素点的方法,这里用迭代器实现

然后是图像界面中的处理函数

#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 dealImage();
void colorSelect();
void changeDis(int);
};

#endif // WIDGET_H

其实现

#include "widget.h"
#include
"ui_widget.h"
#include
<QColorDialog>


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(dealImage()));
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.toAscii().data());
cv::namedWindow(
"image");
cv::imshow(
"image",ColorDetector::getInstance()->getInputImage());
dealImage();
}

void Widget::dealImage(){
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));
//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());
}
dealImage();
}

void Widget::changeDis(int value){
ColorDetector::getInstance()
->setColorDistanceThreshold(value);
dealImage();
}

在QT项目的pro文件中要加入如下几句

INCLUDEPATH += D:\OpenCV\include
LIBS +
= -LD:\OpenCV\lib \
-lopencv_core230 \
-lopencv_highgui230 \
-lopencv_imgproc230

看看最后效果

不同颜色,不同阈值的比较效果

分类:

技术点:

相关文章: