识别黄色的物体受光照影响大,hsv的值可以自己调,用d=f*w/p这条公式求距离误差有点大,可上网找其他的方法。
代码如下:
#include
#include
using namespace std;
using namespace cv;
int main()
{
VideoCapture cap;
cap.open(1); //打开相机
int H_min =2;
int H_max = 15;
int S_min = 44;
int S_max = 255;
int V_min = 91;
int V_max = 255;
Mat temp = Mat::zeros(Size(200, 200), CV_8UC3); //调参窗口的图像
namedWindow("调参窗口", WINDOW_FREERATIO);
namedWindow("识别", WINDOW_FREERATIO);
namedWindow("二值", WINDOW_FREERATIO);
Mat src, dst, stream;
int dist;
while (1)
{
cap >> src;
blur(src, src, Size(3, 3)); //模糊降噪
cvtColor(src, dst, COLOR_BGR2HSV); //转HSV格式
createTrackbar("H_min", "调参窗口", &H_min, 255); //调节HSV的拖动条
createTrackbar("H_max", "调参窗口", &H_max, 255);
createTrackbar("S_min", "调参窗口", &S_min, 255);
createTrackbar("S_max", "调参窗口", &S_max, 255);
createTrackbar("V_min", "调参窗口", &V_min, 255);
createTrackbar("V_max", "调参窗口", &V_max, 255);
inRange(dst, Scalar(H_min, S_min, V_min), Scalar(H_max, S_max, V_max), dst); //转二值
Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5)); //结构元素
morphologyEx(dst, dst, MORPH_OPEN, kernel); //开操作 ——去除杂质
morphologyEx(dst, dst, MORPH_CLOSE, kernel); //闭操作 ——填充小洞
imshow("二值", dst);
Canny(dst, dst, 100, 200); //Canny边缘检测
vector>v; //点容器——用于存放轮廓
findContours(dst, v, RETR_TREE, CHAIN_APPROX_NONE); //发现轮廓
vector> couter(v.size());
Rect rect;
for (size_t i = 0; i < v.size(); i++)
{
if (contourArea(v[i]) > 300 && contourArea(v[i]) < 30000) //筛选轮廓面积
{
approxPolyDP(v[i], couter[i], 10, true);
if (couter[i].size() != 4 ) //筛选规则形状
{
rect = boundingRect(v[i]);
double biw = rect.width / rect.height;
if (rect.area() > 300 && rect.area() < 30000 && biw>0.7 &&biw<2.0) //筛选矩形框面积和矩形宽与高的比值
{
rectangle(src, rect, Scalar(0, 0, 255), 2, 8); //画矩形
double x = 0, y = 0;
x = (rect.br().x + rect.tl().x) / 2;
y = (rect.br().y + rect.tl().y) / 2;
circle(src, Point(x, y), 3, Scalar(255, 0, 0), -1, 8);//画出矩形中心点
/* 已知相机的焦距f,求相机到物体的距离 */
// f=p*d/w,先用 像素宽度*实际距离/物体实际宽度 求出相机焦距
//d=f*w/p 再用 焦距*实际宽度/像素宽度 求距离
double w = 27; //实际宽度
double f = 770; //相机焦距
double p; //像素宽度
double d = 0; //实际距离
p = rect.width;
d = f * w / p;
dist = (int)d;
String str = "distance:" + to_string(dist) + "cm";
putText(src, str, rect.br(), FONT_HERSHEY_PLAIN, 1, Scalar(0, 213, 255), 1, 8);//标出距离
}
}
}
}
imshow("识别", src);
imshow("调参窗口", temp);
waitKey(1);
}
return 0;
}