# How do I find a vertical line in a image?

My current project is to use OpenCV and a webcam to follow a line with the Lego Mindstorm EV3. That would be black tape on a light background. I have a test image (white left, black right) that I can process. The idea is to use moments to find the x location of the vertical line. I can process my test image with cvtColor, GaussianBlur, threshold, erode, dilate, findContours and drawContour. The white region is seen as a block bounded by the edges of the frame. I can create a black border on the contour image to remove the frame edges. Then I am left with a vertical line. FindContours should find the line. But, findContours is area based and I am trying something that is line based. If I findContours of the vertical line, I go back to the edges. What is the contour of a line? I get three contours. 1 left edge and line. 2 line. 3 right edge and line. I could just use the second contour, but that will not expand to a real image with an unknown number of contours. My idea is to find the x location of the vertical line with moments. I can get the average x location of all the moments, but that is misleading and inaccurate. Or, will I have to use BondingRect.

My problem is with OpenCV. Does anyone know OpenCV well enough to suggest a valid approach to solve this problem?

2/20/2018 My commenter wants a real image. A real image makes this more difficult. But, I have provided. The Lego EV3 runs at 300 Hz. So, my simulations are on my desktop (3Gz). The original project is at LeJosNews in java. But, most of the OpenCV documentation I am finding is in C++. I am trying an easy slow start with this project, so I am using C++ at 3Gz. The original core java code is as follows …

private float getMidPoint(int bias)
{
Mat roi = new Mat(camImage, new Rect(10, 2*camImage.rows()/3, camImage.cols()-20,
camImage.rows()/12));
Imgproc.cvtColor(roi, mono, Imgproc.COLOR_BGR2GRAY);
Imgproc.GaussianBlur(mono, blur, new Size(9, 9), 2, 2);
Imgproc.threshold(blur, thresh, 0, 255,
Imgproc.THRESH_BINARY_INV|Imgproc.THRESH_OTSU);
Imgproc.erode(thresh, erodeImg, erode);
Imgproc.dilate(erodeImg, dilateImg, dilate);
List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
Imgproc.findContours(dilateImg, contours, notused, Imgproc.RETR_LIST,
Imgproc.CHAIN_APPROX_SIMPLE);
double minMaxCx = (bias > 0 ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY);
for(MatOfPoint cont : contours)
{
Moments mu = Imgproc.moments(cont, false);
if (mu.get_m00() > 100.0)
{
Rect r = Imgproc.boundingRect(cont);
double cx;
if (bias > 0)
{
cx = r.x + r.width - 12;
if (cx > minMaxCx)
{
minMaxCx = cx;
}
}
else
{
cx = r.x + 12;
if (minMaxCx > cx)
{
minMaxCx = cx;
}
}
}
}
if (Double.isInfinite(minMaxCx))
minMaxCx = roi.cols()/2;
return 1.0f - 2.0f*(float)minMaxCx/roi.cols();
}


And my code in C++ is …

#include "stdafx.h"

#include <iostream>
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"

using namespace ...
edit retag close merge delete