先上代码
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>
#include "WzSerialPort.h"
#define mid 320
using namespace cv;
using namespace std;
Mat img;
VideoCapture cap(0);
// COLOR VALUES
// hmin, smin, vmin hmax, smax, vmax
vector<vector<int>> myColors{ {0, 154, 159, 5, 255, 255}, // Red
/*{91, 12, 33, 124, 255, 229}// Blue*/ };
int getContours(Mat image) {
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(image, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
vector<vector<Point>> conPoly(contours.size());
vector<Rect> boundRect(contours.size());
vector<int> gap;
vector<int> absgap;
double gapmin;
Point gmin;
Point myPoint(0, 0);
int j = 0;
for (int i = 0; i < contours.size(); i++)
{
int area = contourArea(contours[i]);
if (area > 10000)
{
float peri = arcLength(contours[i], true);
approxPolyDP(contours[i], conPoly[i], 0.02 * peri, true);
//cout << conPoly[i].size() << endl;
boundRect[i] = boundingRect(conPoly[i]);
myPoint.x = boundRect[i].x + boundRect[i].width / 2;
myPoint.y = boundRect[i].y;
drawContours(img, conPoly, i, Scalar(255, 0, 255), 2);
rectangle(img, boundRect[i].tl(), boundRect[i].br(), Scalar(0, 255, 0), 5);
circle(img, Point(myPoint.x, myPoint.y), 7, Scalar(66,66,66), FILLED);
gap.push_back(mid - myPoint.x);
absgap.push_back(abs(gap[j]));
cout << gap[j] <<",";
j++;
}
}
if (myPoint.x != 0)
{
for (int i = 0; i < absgap.size(); i++) cout << absgap[i] << " ";
minMaxLoc(absgap, &gapmin, NULL, &gmin, NULL);
cout << endl << "min is" << gapmin << endl << "gmin is" << gmin << endl;
return gap[gmin.x];
}
else return 0;
}
int findColor(Mat img)
{
Mat imgHSV;
cvtColor(img, imgHSV, COLOR_BGR2HSV);
for (int i = 0; i < myColors.size(); i++)
{
Scalar lower(myColors[i][0], myColors[i][1], myColors[i][2]);
Scalar upper(myColors[i][3], myColors[i][4], myColors[i][5]);
Mat mask;
inRange(imgHSV, lower, upper, mask);
return getContours(mask);
}
}
/// //串口通讯部分/
void senddis(int dis)
{
WzSerialPort w;
if (w.open("COM7", 115200, 0, 8, 1))
{
char temp[10];
sprintf_s(temp,"%d",dis);
w.send(temp, 10);
cout << "send finished...";
w.close();
}
else
{
cout << "open serial port failed...";
}
}
void receivedis()
{
WzSerialPort w;
if (w.open("COM6", 9600, 0, 8, 1))
{
char buf[1024];
while (true)
{
memset(buf, 0, 1024);
w.receive(buf, 1024);
cout << buf;
}
}
}
void main() {
while (true) {
cap.read(img);
int dis = findColor(img);
if (dis != 0)
{
cout << "位置是" << dis << endl;
senddis(dis);
}
line(img, Point(mid, 0), Point(mid, 480), Scalar(0, 0, 255), 1);//在中间画线
imshow("Image", img);
waitKey(1);
}
}
本次代码是用于对某一特定物体进行识别并且得到位置坐标。颜色的识别可以参考我之前的一篇https://blog.csdn.net/m0_52430942/article/details/118655479?spm=1001.2014.3001.5501
由于个人的需要我还加上了串口通讯,串口通讯部分将会在下一篇进行讲解。
以下是纯识别部分
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>
#define mid 320
using namespace cv;
using namespace std;
Mat img;
VideoCapture cap(0);
/ COLOR VALUES
// hmin, smin, vmin hmax, smax, vmax
vector<vector<int>> myColors{ {0, 154, 159, 5, 255, 255}, // Red
/*{91, 12, 33, 124, 255, 229}// Blue*/ };
int getContours(Mat image) {
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(image, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
vector<vector<Point>> conPoly(contours.size());
vector<Rect> boundRect(contours.size());
vector<int> gap;
vector<int> absgap;
double gapmin;
Point gmin;
Point myPoint(0, 0);
int j = 0;
for (int i = 0; i < contours.size(); i++)
{
int area = contourArea(contours[i]);
if (area > 10000)
{
float peri = arcLength(contours[i], true);
approxPolyDP(contours[i], conPoly[i], 0.02 * peri, true);
//cout << conPoly[i].size() << endl;
boundRect[i] = boundingRect(conPoly[i]);
myPoint.x = boundRect[i].x + boundRect[i].width / 2;
myPoint.y = boundRect[i].y;
drawContours(img, conPoly, i, Scalar(255, 0, 255), 2);
rectangle(img, boundRect[i].tl(), boundRect[i].br(), Scalar(0, 255, 0), 5);
circle(img, Point(myPoint.x, myPoint.y), 7, Scalar(66,66,66), FILLED);
gap.push_back(mid - myPoint.x);
absgap.push_back(abs(gap[j]));
cout << gap[j] <<",";
j++;
}
}
if (myPoint.x != 0)
{
for (int i = 0; i < absgap.size(); i++) cout << absgap[i] << " ";
minMaxLoc(absgap, &gapmin, NULL, &gmin, NULL);
cout << endl << "min is" << gapmin << endl << "gmin is" << gmin << endl;
return gap[gmin.x];
}
else return 0;
}
int findColor(Mat img)
{
Mat imgHSV;
cvtColor(img, imgHSV, COLOR_BGR2HSV);
for (int i = 0; i < myColors.size(); i++)
{
Scalar lower(myColors[i][0], myColors[i][1], myColors[i][2]);
Scalar upper(myColors[i][3], myColors[i][4], myColors[i][5]);
Mat mask;
inRange(imgHSV, lower, upper, mask);
return getContours(mask);
}
}
void main() {
while (true) {
cap.read(img);
int dis = findColor(img);
if (dis != 0)
{
cout << "位置是" << dis << endl;
senddis(dis);
}
line(img, Point(mid, 0), Point(mid, 480), Scalar(0, 0, 255), 1);//在中间画线
imshow("Image", img);
waitKey(1);
}
}
vector<vector<int>> myColors{ {0, 154, 159, 5, 255, 255}, // Red
/*{91, 12, 33, 124, 255, 229}// Blue*/ };
这一小部分就是我们指定物体的hsv阈值,修改就好。
Scalar lower(myColors[i][0], myColors[i][1], myColors[i][2]);
Scalar upper(myColors[i][3], myColors[i][4], myColors[i][5]);
这里是矩阵的位置坐标不用修改。
if (area > 10000)
{
float peri = arcLength(contours[i], true);
approxPolyDP(contours[i], conPoly[i], 0.02 * peri, true);
//cout << conPoly[i].size() << endl;
boundRect[i] = boundingRect(conPoly[i]);
myPoint.x = boundRect[i].x + boundRect[i].width / 2;
myPoint.y = boundRect[i].y;
drawContours(img, conPoly, i, Scalar(255, 0, 255), 2);
rectangle(img, boundRect[i].tl(), boundRect[i].br(), Scalar(0, 255, 0), 5);
circle(img, Point(myPoint.x, myPoint.y), 7, Scalar(66,66,66), FILLED);
gap.push_back(mid - myPoint.x);
absgap.push_back(abs(gap[j]));
cout << gap[j] <<",";
j++;
}
这里是框选出我们物体的轮廓并且是大于某个值才能选择 if (area > 10000)