循迹小车的视觉处理部分
前言废话:最近寒假在家没事干,想学习一下循迹小车的视觉处理部分,上网想找一下开源也没找到多少,看到有用神经网络做的,但是我神经网络还能不熟悉,所以就没向那边想,上网看了一些思路,就东拼西凑的自己写了一点粗略的视觉处理部分(仅仅只是粗略的处理),后面还是有很的地方得慢慢的去优化的然后落地的差不多也就是想记个笔记
找目区域
首先想到的就是颜色识别嘛,转hsv然后调参数(感觉可以试一下通道分离来做可能效果会一点,或者直接灰度处理二值化),这里为了可以方便一边找到合适的值我们可以创建一个进度条
//转hsv空间
Mat image_hsv;
cvtColor(frame,image_hsv,COLOR_BGR2HSV);
创建进度条
nt hmin_w = 0;
int hmax_w = 204;
int smin_w = 0;
int smax_w = 255;
int vmin_w = 164;
int vmax_w = 255;
namedWindow("Color");
createTrackbar("LowH", "Color", &hmin_w, 255);
createTrackbar("LowS", "Color", &smin_w, 255);
createTrackbar("LowV", "Color", &vmin_w, 255);
createTrackbar("HighH", "Color", &hmax_w, 255);
createTrackbar("HighS", "Color", &smax_w, 255);
createTrackbar("HighV", "Color", &vmax_w, 255);
然后就是图像的预处理部分
这一部分可以加其他的图像处理以达到更好的效果;
我这里的处理方法很简单,就只进行简单的处理
Mat imgThresholded;
inRange(image_hsv, Scalar(hmin_w,smin_w,vmin_w), Scalar(hmax_w, smax_w,vmax_w),imgThresholded);
Mat element = getStructuringElement(MORPH_RECT, Size(2, 2));
//morphologyEx( imgThresholded,imgThresholded, MORPH_OPEN, element);
//闭操作 (连接一些连通域)
morphologyEx(imgThresholded, imgThresholded, MORPH_OPEN, element);
//进行边缘检测
Mat edges;
Canny(imgThresholded,edges,50,150);
vector<Vec4i> hierarchy;
vector<vector<Point>>contours;
计算
以屏幕的中心为参考点,计算轨道的中心与其的距离,来作为是否偏航的判断;
全部代码:
#include<opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int find_max_Area(vector<double>Area)
{
int max=1;
for (int i = 0; i < Area.size(); ++i) {
if (Area[i]>Area[max])
{
max=i;
}
}
cout<<"MaxArea"<<Area[max]<<endl;
return max;
}
int main()
{
Mat frame;
VideoCapture capture(0);
while(1)
{
capture>>frame;
namedWindow("frame",WINDOW_AUTOSIZE);
imshow("frame",frame);
//查看屏幕窗口的大小
cout<<"frame_clos: "<<frame.cols<<endl;
cout<<"frame_rows: "<<frame.rows<<endl;
//转hsv空间
Mat image_hsv;
cvtColor(frame,image_hsv,COLOR_BGR2HSV);
//设置颜色的提取范围;
// int hmin_w;
// int hmax_w;
//
// int smin_w;
// int smax_w;
//
// int vmin_w;
// int vmax_w;
int hmin_w = 0;
int hmax_w = 204;
int smin_w = 0;
int smax_w = 255;
int vmin_w = 164;
int vmax_w = 255;
namedWindow("Color");
createTrackbar("LowH", "Color", &hmin_w, 255);
createTrackbar("LowS", "Color", &smin_w, 255);
createTrackbar("LowV", "Color", &vmin_w, 255);
createTrackbar("HighH", "Color", &hmax_w, 255);
createTrackbar("HighS", "Color", &smax_w, 255);
createTrackbar("HighV", "Color", &vmax_w, 255);
Mat imgThresholded;
inRange(image_hsv, Scalar(hmin_w,smin_w,vmin_w), Scalar(hmax_w, smax_w,vmax_w),imgThresholded);
Mat element = getStructuringElement(MORPH_RECT, Size(2, 2));
//morphologyEx( imgThresholded,imgThresholded, MORPH_OPEN, element);
//闭操作 (连接一些连通域)
morphologyEx(imgThresholded, imgThresholded, MORPH_OPEN, element);
//进行边缘检测
Mat edges;
Canny(imgThresholded,edges,50,150);
vector<Vec4i> hierarchy;
vector<vector<Point>>contours;
findContours(edges,contours,hierarchy,RETR_TREE,CHAIN_APPROX_SIMPLE);
drawContours(frame,contours, -1,Scalar(0,255,0),3);
vector<double>Area(contours.size());
//进行条件的筛选,遍历每一个轮廓找到自己想你要的轮廓
for (int i = 0; i < contours.size(); ++i) {
Area[i] = contourArea(contours[i]);
cout<<"第"<<i<<"area"<<Area[i]<<endl;
// if(Area[i]>10)
// {
// drawContours(frame,contours, i,Scalar(0,255,0),3);
// }
}
// int max_area_contours= find_max_Area(Area);
//找外接矩形
vector<Rect>boundRect(contours.size());
for (int i = 0; i < contours.size(); ++i) {
boundRect[i]= boundingRect(contours[i]);
}
//找轨道的中心点
vector<Point>center(boundRect.size());
for (int i = 0; i < boundRect.size(); ++i) {
center[i]=(boundRect[i].tl()+boundRect[i].br())/2;//通过最小的外接矩形对角线的两个点的坐标来计算一条边的中心点
cout<<"第"<<i<<"个轮廓的中心点"<<center[i]<<endl;
}
Point center_end;
center_end=(center[0]+center[1])/2;//计算轨道的中心点
cout<<"轨道的中心点"<<center_end<<endl;
//在画圆的时候要将坐标乘以2这里我也没有找到解释的答案
circle(frame,center_end*2,7,Scalar(0,0,255),-1,8,1);
circle(frame,Point (640,480),7,Scalar(0,0,255),-1,8,1);//屏幕中心的点Point的实际值是(320,240)
//计算屏幕中心和轨道中心点的偏差距离;
Point Screen_center(320,240);
float distance = sqrt(pow(center_end.x-Screen_center.x,2)+ pow(center_end.y-Screen_center.y,2));
cout<<"相差的距离"<<distance<<endl;
//line也得乘以2,服了
line(frame,center_end*2,Screen_center*2,Scalar(0,255,0),3,8,1);
char string[10];
sprintf(string,"%0.2f",distance);
String distance_string("distance");
distance_string+=string;
putText(frame,distance_string,Screen_center,FONT_HERSHEY_PLAIN,2,Scalar(0,255,0),2, false);
//显示窗口部分
imshow("Color",imgThresholded);
imshow("dis",frame);
imshow("edges",edges);
waitKey(1);
}
}
演示视频
循迹
后面会慢慢的优化这个小玩意儿,有很多的不足