目录
- 1. 步骤
- 1.1 selector选择器
- 1.2 detector探测器
- 2. 代码
- 3. 效果图
1. 步骤
1.1 selector选择器
- 我们可以选择摄网络摄像头提供的第一帧,在该图像上选择停车位。为此,保存并使用该图像选择停车位。
- 使用selectROIs函数标记停车位。ROI被定义为感兴趣的区域,代表图像的一部分,我们将在其上应用不同的函数以及滤波器来获取结果
/*
@param windowName 选择窗口显示的名称
@param img 输入的image
@param boundingBoxes 选择的框
@param showCrosshair 如果为true显示选取内部的中心线,否则不显示
@param fromCenter 如果为真,选择中心将匹配初始鼠标位置。在相反的情况下,选择矩形的一个角将对应于鼠标的初始位置,是一个非常重要的参数,因为如果将其设置为True,则正确的选择会困难得多
*/
void selectROIs(const String& windowName, InputArray img,
CV_OUT std::vector<Rect>& boundingBoxes, bool showCrosshair = true, bool fromCenter = false);
选择所有停车位之后,可以将它们写入.csv文件里,就不用每次都要去手动选择车位框了。
1.2 detector探测器
现在我们已经选择了停车位,是时候进行一些图像处理了。解决这个问题的方法如
下:
- 从.csv文件获取坐标。
- 从中构建新图像。
- 应用OpenCV中可用的Canny函数。
- 计算新图像内的白色像素。
- 建立一个点内的像素范围将被占用。
- 在实时供稿上绘制一个红色或绿色矩形。
2. 代码
void drawRectangle(cv::Mat& img, cv::Rect rect, int lowThreshold, int highThreshold, int minPix, int maxPix, int &spots_loc)
{
cv::Mat sub_img = img(rect);
cv::Mat edges;
cv::Canny(sub_img, edges, lowThreshold, highThreshold);
int pix = cv::countNonZero(edges);
if (pix >= minPix && pix <= maxPix)
{
cv::rectangle(img, rect, cv::Scalar(0, 255, 0), 3);
spots_loc++;
}
else
{
cv::rectangle(img, rect, cv::Scalar(0, 0, 255), 3);
}
}
int main()
{
char* path = "E:\\code\\Yolov5_Tensorrt_Win10-master\\pictures\\1.png";
Mat src = imread(path);
if (src.empty()) {
return -1;
}
std::vector<cv::Rect> result_pots;
cv::selectROIs("roi", src, result_pots, false, false);
cv::namedWindow("parameters");
int val1 = 186, val2 = 122, val3 = 100, val4 = 800;
cv::createTrackbar("Threshold1", "parameters", &val1, 700);
cv::createTrackbar("Threshold2", "parameters", &val2, 700);
cv::createTrackbar("Min pixels", "parameters", &val3, 1500);
cv::createTrackbar("Max pixels", "parameters", &val4, 1500);
while (true)
{
int spots_loc = 0;
int min = cv::getTrackbarPos("Min pixels", "parameters");
int max = cv::getTrackbarPos("Max pixels", "parameters");
int lowThreshold = cv::getTrackbarPos("Threshold1", "parameters");
int highThreshold = cv::getTrackbarPos("Threshold2", "parameters");
for (const auto& rect : result_pots)
{
drawRectangle(src, rect, lowThreshold, highThreshold, min, max, spots_loc);
}
std::string text = cv::format("Available spots:%d", spots_loc);
cv::putText(src, text, { 20, 30 }, cv::FONT_HERSHEY_PLAIN, 1, cv::Scalar(0,255,0), 2);
cv::imshow("src", src);
if ((cv::waitKey(1) & 0xFF) == 'q')
break;
}
return 0;
}
3. 效果图
注意:
- 为实时调整参数,构建一些轨迹栏,通过调整参数可以正确识别空闲停车位
- 显示中的Available spots:数字有叠加,因为没有视频,是靠一张图片循环的
- 这里的select 框并没有存文件,每次需要手动选择