9

I am trying to use opencv to automatically find and locate all parking spots in an empty parking lot.

Currently, I have a code that thresholds the image, applies canny edge detection, and then uses probabilistic hough lines to find the lines that mark each parking spot.

The program then draws the lines and the points that make up the lines

Here is the code:

#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;
}

Currently, my main problem is figuring out how to extrapolate the line data to find the locations of each parking space. My goal is to have opencv find the parking spaces and draw out rectangles on each parking space with a number labeling the spots.

I think there are some major problems with the method I am currently using, because as shown in the output images, opencv is detecting multiple points on the line other than the 2 endpoints. That might make it very hard to use opencv to connect 2 adjacent endpoints.

I read something about using convex hull, but I am not exactly sure what it does and how it works.

Any help will be appreciated. Here are the output images from my program: http://imageshack.us/photo/my-images/22/test1hl.png/

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

trumpetlicks
  • 7,033
  • 2
  • 19
  • 33
tincan
  • 187
  • 1
  • 4
  • 12
  • Can you include the inputs without any processing ? For the problem of detecting more lines/points than you are after, RANSAC is likely to be better at solving such problem than relying on Hough. – mmgp Feb 02 '13 at 00:21
  • One thing that comes to my mind is to first [dilate](http://docs.opencv.org/modules/imgproc/doc/filtering.html#dilate) the image to make the lines appear thinner. Then maybe opencv will only detect the 2 endpoints per line. – Tom Knapen Feb 02 '13 at 01:42
  • @TomKnapen you are mixing dilation with erosion. In these examples, the lines are bright, so a dilation will make them larger. So let us replace your suggestion to erosion. Now you can break thin lines. But this is all irrelevant actually, he is using Canny which gives one-thick-wide edges. – mmgp Feb 02 '13 at 02:39
  • @mmgp The inputs are the window on the right side. It is an image of a parking taken from my webcam. I will do some research on ransac and see how it can be implemented. So currently, I am using Canny, but I think there might be a better way of doing this, since each adjacent quadrilaterals that mark the parking spots can share an edge. Should I be using erosion to make the line thinner so only one line is detected in canny? – tincan Feb 02 '13 at 02:48
  • @TianYao maybe I wasn't clear enough in my request, I simply asked you to include the images without any processing. The images you included here are screenshots, my suggestion is to include some of the actual frames you have (not a screenshot of them, or anything else). To make the lines thinner the correct approach requires a thinning algorithm, which might be implemented using hit-or-miss transform (not available in opencv), but there are also other ways to do it. But, in order to give more accurate suggestions (and not only guesses), we need the actual data you are working with. – mmgp Feb 02 '13 at 02:57
  • Here is the original image: http://www.photographersgallery.com/i/full/parking_lot_markings.jpg Here is an mpeg4 encoded avi file of what my webcam records (recorded with opencv viderwriter): https://www.dropbox.com/s/ysokrddv88wi01k/test.avi – tincan Feb 02 '13 at 03:23

1 Answers1

3

Consider thinning your binary image, and then detect the end points and the branch points. Here is one such result based on the images provided; end points are in red and branch points are in blue.

enter image description here

Now you can find the locations of the parking spaces. A pair of blue dots is always connected by a single edge. Each blue dot is connected to either two or three red points. Then there are several ways to find the parking space formed by two blue dots and two red dots, the simplest is along the lines: find the closest pair of red dots where one dot is connected to a certain blue dot, and the other red point is connected to the other blue dot. This step can also be complemented by checking how close to parallel lines are the edges considered.

mmgp
  • 18,901
  • 3
  • 53
  • 80
  • ok great thanks. did you use erosion to thin the thresholded image? I will try this tomorrow morning and see how it turns out. – tincan Feb 02 '13 at 05:26
  • In principle yes, see http://en.wikipedia.org/wiki/Morphological_skeleton for the classical binary morphological skeleton construction. – mmgp Feb 02 '13 at 05:28
  • I am currently stuck on getting a skeleton of the binary image. I am basically using the optimized code from here: http://felix.abecassis.me/2011/09/opencv-morphological-skeleton/ , except instead of doing erode and dilate, I am using morphologyEx to do an opening morphology. And at the end, I transfer skel into a global Mat that is used for Canny edge detection. The problem is that the program hangs when I run it. The window shows up, but no image is shown. I've isolated the problem to the do while loop, but I am not sure what exactly is causing it. – tincan Feb 02 '13 at 23:45
  • So after some testing, I noticed that countNonZero is never going to 0, which means that the do while loop goes on for infinite. I will try to out put the images at each stage to see if any changes occured – tincan Feb 03 '13 at 01:49
  • Oops, nvm. I realized that I was copying to the wrong Mat at the end of the loop, which means that it is processing the same image over and over again. However, the final skeletal image is very noisy. But I don't think that will be much of a problem. – tincan Feb 03 '13 at 02:05