使用 OpenCV 检测停车位

Posted

技术标签:

【中文标题】使用 OpenCV 检测停车位【英文标题】:Using OpenCV to detect parking spots 【发布时间】:2013-01-17 08:07:39 【问题描述】:

我正在尝试使用opencv自动查找并定位空停车场中的所有停车位。

目前,我有一个代码可以对图像进行阈值检测,应用精明的边缘检测,然后使用概率霍夫线来找到标记每个停车位的线。

然后程序绘制线条和构成线条的点

代码如下:

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"

#include <iostream>

using namespace cv;
using namespace std;

int threshold_value = 150;
int threshold_type = 0;;
int const max_value = 255;
int const max_type = 4;
int const max_BINARY_value = 255;

int houghthresh = 50;

char* trackbar_value = "Value";

char* window_name = "Find Lines";

int main(int argc, char** argv)

 const char* filename = argc >= 2 ? argv[1] : "pic1.jpg";
 VideoCapture cap(0);
 Mat src, dst, cdst, tdst, bgrdst;
 namedWindow( window_name, CV_WINDOW_AUTOSIZE );

 createTrackbar( trackbar_value,
          window_name, &threshold_value,
          max_value);

while(1)

 cap >> src;
 cvtColor(src, dst, CV_RGB2GRAY);
 threshold( dst, tdst, threshold_value, max_BINARY_value,threshold_type );
 Canny(tdst, cdst, 50, 200, 3);
 cvtColor(tdst, bgrdst, CV_GRAY2BGR);

  vector<Vec4i> lines;
  HoughLinesP(cdst, lines, 1, CV_PI/180, houghthresh, 50, 10 );
  for( size_t i = 0; i < lines.size(); i++ )
  
    Vec4i l = lines[i];
    line( bgrdst, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0,255,0), 2, CV_AA);
    circle( bgrdst,
         Point(l[0], l[1]),
         5,
         Scalar( 0, 0, 255 ),
         -1,
         8 );
    circle( bgrdst,
         Point(l[2], l[3]),
         5,
         Scalar( 0, 0, 255 ),
         -1,
         8 );
  

 imshow("source", src);
 imshow(window_name, bgrdst);

 waitKey(1);

 return 0;

目前,我的主要问题是弄清楚如何推断线数据以找到每个停车位的位置。我的目标是让 opencv 找到停车位,并在每个停车位上画出矩形,并用数字标记停车位。

我认为我目前使用的方法存在一些主要问题,因为如输出图像所示,opencv 正在检测线上除了 2 个端点之外的多个点。这可能会使使用 opencv 连接 2 个相邻端点变得非常困难。

我读过一些关于使用凸包的文章,但我不确定它的作用和工作原理。

任何帮助将不胜感激。 这是我的程序的输出图像: http://imageshack.us/photo/my-images/22/test1hl.png/

http://imageshack.us/photo/my-images/822/test2lw.png/

【问题讨论】:

你能在没有任何处理的情况下包含输入吗?对于检测到比你想要的更多的线/点的问题,RANSAC 可能比依赖 Hough 更擅长解决此类问题。 我想到的一件事是首先dilate图像使线条看起来更细。那么也许opencv只会检测每行的2个端点。 @TomKnapen 您将膨胀与腐蚀混合在一起。在这些示例中,线条很亮,因此膨胀会使它们变大。因此,让我们将您的建议替换为侵蚀。现在你可以打破细线。但这实际上都无关紧要,他使用的是 Canny,它可以提供一厚宽的边缘。 @mmgp 输入是右侧的窗口。这是从我的网络摄像头拍摄的停车场图像。我将对ransac做一些研究,看看它是如何实现的。所以目前,我正在使用 Canny,但我认为可能有更好的方法来做到这一点,因为标记停车位的每个相邻四边形都可以共享一条边。我应该使用腐蚀来使线条变细,以​​便在 canny 中只检测到一条线吗? @TianYao 也许我的要求不够清楚,我只是要求您将图像包含在没有任何处理的情况下。您在此处包含的图像是屏幕截图,我的建议是包含您拥有的一些实际帧(不是它们的屏幕截图或其他任何内容)。为了使线条更细,正确的方法需要细化算法,该算法可以使用命中或未命中变换(在 opencv 中不可用)来实现,但也有其他方法可以做到这一点。但是,为了提供更准确的建议(而不仅仅是猜测),我们需要您使用的实际数据。 【参考方案1】:

考虑细化二值图像,然后检测端点和分支点。这是基于提供的图像的一个这样的结果;端点为红色,分支点为蓝色。

现在您可以找到停车位的位置。一对蓝点总是由一条边连接。每个蓝点连接到两个或三个红点。那么有几种方法可以找到由两个蓝点和两个红点组成的停车位,最简单的就是顺势而为:找到最近的一对红点,其中一个点连接某个蓝点,另一个红点连接到另一个蓝点。这一步也可以通过检查所考虑的边缘与平行线的接近程度来补充。

【讨论】:

好的,非常感谢。您是否使用侵蚀来稀释阈值图像?明天早上我会试试这个,看看结果如何。 原则上是的,参见en.wikipedia.org/wiki/Morphological_skeleton 了解经典的二元形态骨架构造。 我目前正忙于获取二进制图像的骨架。我基本上使用这里的优化代码:felix.abecassis.me/2011/09/opencv-morphological-skeleton,除了不做腐蚀和扩张,我使用morphologyEx 做一个开放的形态。最后,我将 skel 转移到用于 Canny 边缘检测的全局 Mat 中。问题是程序在我运行时挂起。窗口出现,但没有显示图像。我已将问题隔离到 do while 循环,但我不确定究竟是什么原因造成的。 所以经过一些测试,我注意到 countNonZero 永远不会为 0,这意味着 do while 循环会无限循环。我会尝试在每个阶段输出图像,看看是否发生任何变化 糟糕,nvm。我意识到我在循环结束时复制到了错误的 Mat,这意味着它一遍又一遍地处理相同的图像。然而,最终的骨骼图像非常嘈杂。但我认为这不是什么大问题。

以上是关于使用 OpenCV 检测停车位的主要内容,如果未能解决你的问题,请参考以下文章

树莓派+OpenCV,自制一台违章摄像头

选择区域 OpenCV

基于 Python 和 OpenCV 构建智能停车系统

基于OpenCV构建停车场车位识别项目

关于违章停车检测方法的思考

opencv项目week3