opencv——颜色识别滑稽
注:本文非标准教程,仅是总结个人学习过程,可能存在纰漏,如有错误之处欢迎留言告知,非常感谢
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/core/core.hpp>
#include <math.h>
using namespace std;
using namespace cv;
double t1, t2, FPS;
Mat H;
Mat H_x,H_y,abs_H_x,abs_H_y;
int main()
{
VideoCapture capture(0); //括号里有坑
while (1)
{
t1 = static_cast<double>(getTickCount());
Mat frame; //调用摄像头
capture >> frame;
resize(frame, frame, Size(640, 480));
Sobel(frame,H_x,CV_16S,0,1,3,1,1,BORDER_DEFAULT);
convertScaleAbs(H_x,abs_H_x);
Sobel(frame,H_y,CV_16S,0,1,3,1,1,BORDER_DEFAULT);
convertScaleAbs(H_y,abs_H_y);
addWeighted(abs_H_x,0.5,abs_H_y,0.5,0,H);
medianBlur(H,H,9); //中值滤波 除噪
blur(H, H, Size(5,5));
Mat element = getStructuringElement(MORPH_RECT,Size(3, 3));
inRange(frame, Scalar(75, 148, 140), Scalar(125, 200, 230), H);
//调节图像颜色信息(H)、饱和度(S)、亮度(V)区间
//H——Hue即色相,就是我们平时所说的红、绿;在HSV模型中,用度数来描述色相,其中红色对应0度,绿色对应120度,蓝色对应240度。
//S——Saturation即饱和度,色彩的深浅度,对于一种颜色比如红色,对应在画水彩的时候即一种颜料加上不同分量的水形成不同的饱和度。
//V——Value即色调,色彩的亮度 ,这个在调整亮度的时候比较常见。
Mat contoursimg = Mat::zeros(H.size(), CV_8UC3); //返回指定的大小和类型的零数组
vector<vector<Point>> contours;
vector<Vec4i> contoursarray;
findContours(H, contours, contoursarray, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
vector<Rect> boundRect(contours.size());
vector<Rect> boundRect2;
for (int i = 0; i < contours.size(); i++)
{
drawContours(H, contours, i, Scalar(255), 2, 8, contoursarray);
}
for (int idx = 0; idx < contours.size(); ++idx)
{
boundRect[idx] = boundingRect(Mat(contours[idx]));
boundRect2.push_back(boundRect[idx]);
}
for (int b = 0; b < boundRect2.size(); ++b)
{
// 可以再加些限制条件
if(boundRect2[b].area() >9999)
rectangle(frame, boundRect2[b].tl(), boundRect2[b].br(), cv::Scalar(255, 5, 250), 3, 8, 0); //画矩形
for (int c = 0; c < boundRect2.size(); ++c)
{
int rect_x1 = boundRect2[b].x + boundRect2[b].width / 2; //第一个轮廓在X轴上的中点
int rect_y1 = boundRect2[b].y + boundRect2[b].height / 2; //第一个轮廓在Y轴上的中点
int rect_x2 = boundRect2[c].x + boundRect2[c].width / 2; //第二个轮廓在X轴上的中点
int rect_y2 = boundRect2[c].y + boundRect2[c].height / 2; //第二个轮廓在Y轴上的中点
{
if (fabs(rect_x2 - rect_x1) != 0)
{
float k = (float)abs(rect_y2 - rect_y1) / (float)abs(rect_x2 - rect_x1); //求斜率
if (k >= 0 && k < 0.5)
{
Point p0 = Point(rect_x1, rect_y1); //矩形中点p0
Point p1 = Point(rect_x2, rect_y2); //矩形中点p1
Point p_center1 = Point((rect_x2 + rect_x1) / 2, (rect_y1 + rect_y2) / 2); //取连线的中点
double L1 = boundRect2[b].height; //第一个矩形的高
double L2 = boundRect2[c].height; //第二个矩形的高
cout << p_center1 << ' ' << endl; //两矩形连线的中点
}
}
}break;
}
}
t2 = ((double)getTickCount() - t1) / getTickFrequency(); //计时结束
FPS = 1.0 / t2; //计算帧率
cout << "运行时间:" << t2 << endl << "帧率:" << FPS << endl;
imshow("原", frame);
imshow("轮廓图", H);
char key = (char)waitKey(1);
if (key == 27)
break;
}
return 0;
}
//通过限制滑稽的长宽,来识别
主要是调 inRange里面的值。