Reputation: 3130
I have images that consist of vegetation disponsed in lines (may or may not be straight lines).
I need to implement an algorithm that identifies those lines and produces a binary mask image tagging the vegetation pixels. This mask can whether be a dense mask (flagging all the identified vegetation pixels) or skeleton mask (1-pixel wide lines identifying the center of the vegetation lanes).
Here is an example of input images:
And here is one of the possible expected outputs:
So far, I've tried the following approaches which result in the following problems:
Anyone has more ideas?
Thanks
Upvotes: 2
Views: 137
Reputation: 21233
If working in RGB color space does not help you, try a different one. For the particular image given, I used the HSV color space.
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
cv2.imshow('hsv.jpg', hsv)
saturation_channel = hsv[:,:,1]
cv2.imshow('saturation_channel.jpg', saturation_channel)
median = np.median(saturation_channel)
std = np.std(saturation_channel)
ret,thresh1 = cv2.threshold(saturation_channel, int(median - (1.05 * std)), 255,cv2.THRESH_BINARY_INV)
cv2.imwrite('thresh1.jpg', thresh1)
NOTE: You can also convert the image to LAB color space and visualize the different channels.
The same image in LAB color space:
Upvotes: 3
Reputation: 6468
You can blur the image before applying Canny and then remove Canny noise by calculating best threshold. After that you can use HoughLinesP
or your method of choice to detect the lines.
cv::Mat src=imread("image.png",-1),dst;
cv::GaussianBlur(src, dst, Size(3,3), 1.0); //blur the source image
cv::cvtColor(dst,dst,cv::COLOR_BGR2GRAY); //convert to gray
cv::Scalar m = cv::mean(dst); //calculate mean
//Calculate lower and upper threshold based on mean
double sigma = 0.33;
double lower_thresh = int(std::max((double)0, ((1.0 - sigma) * m[0])));
double upper_thresh = int(std::min((double)255, ((1.0 + sigma) * m[0])));
cv::Canny(dst, dst, lower_thresh, upper_thresh, 3); //apply canny
Blurred image:
Canny:
Upvotes: 0