0

In my project, I am trying to detect empty space using openCV in C++.

This is my code:

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main()
{

Mat img = imread("D:/Downloads/residence-g1678df24f_1280.jpg",IMREAD_COLOR);
Mat img2;
Mat img3;
Canny(img, img2, 100, 100);
threshold(img2, img3,100,255,THRESH_BINARY);
if (img.empty())
{
    cout << "There was an error while opening your image";
}
vector<KeyPoint> keypoints;
SimpleBlobDetector::Params params;

params.minThreshold = 10;
params.maxThreshold = 200;

params.filterByColor = true;
params.blobColor = 0;

Ptr<SimpleBlobDetector> detector = SimpleBlobDetector::create(params);
 detector->detect( img3, keypoints);
 Mat im_with_keypoints;

 drawKeypoints(img3, keypoints, im_with_keypoints, Scalar(0, 0, 255), DrawMatchesFlags::DRAW_RICH_KEYPOINTS);

imshow("Blob", im_with_keypoints);
waitKey(0);
return 0;
    
}

The output that I get is this: enter image description here

What I want to get as an output is an image that detects the groups of pixels of a specific color (in this case- black) that together have an area greater than some value. To illustrate what I want, I have attached an image below which I have altered using paint manually:

enter image description here

Is there any library that will allow me to do this ? I even tried training a HAAR Cascade classifier with only black images as positive, but even that didn't work. Is there like a predefined library that will help me do this, or do I have to make one myself ? If possible, I want to find the biggest group (area) of pixels of the same color. It need not be of any particular shape.

NOTE: I even looked at this approach How to detect region of large # of white pixels using OpenCV?, but it does not seem to meet my requirements.

Original image: enter image description here

theboss12k
  • 125
  • 8
  • distance transform. on the edge picture. not everything is a library. – Christoph Rackwitz Aug 24 '22 at 10:10
  • Distance transform will help altering the image, but will it help me actually get how much `empty space` there is in the image ? – theboss12k Aug 24 '22 at 10:24
  • apply it. look at the result. then you'll see. you aren't asking the questions you _would_ if you looked at the distance field already. – Christoph Rackwitz Aug 24 '22 at 10:35
  • Unclear what you exactly want to find. All such regions (there are a lot of overlapping ones) or a single one of them? Or the biggest one? Etc... Does it have to be rectangular regions? – Micka Aug 24 '22 at 10:48
  • have a look at: https://stackoverflow.com/questions/70362355/finding-largest-inscribed-rectangle-in-polygon/70365569#70365569 and https://github.com/lukasalexanderweber/lir which can probably be adapted to your problem. – Micka Aug 24 '22 at 10:51
  • @Micka, I edited the question to make my requirements more clear. Thanks for the advice :) – theboss12k Aug 24 '22 at 11:37
  • @ChristophRackwitz, I did distance transform using `distanceTransform(img3,img4,DIST_C,3);`, where img4 is the new image. However, the result is exactly the same as img3 – theboss12k Aug 24 '22 at 11:42
  • @theboss12k try `distanceTransform(255-img3,img4,DIST_C,3);` and maybe scale `img4` before imshow. Because of assumed use cases, distanceTransform computes in the white regions the distances to the next black pixel (whichs is non-intuitive). Since there are only white edge pixels of width 1 in your image, the distance transform there will be either 0 or 1. – Micka Aug 24 '22 at 11:46
  • @theboss12k if the regions may have any shape, try thresholding the desired color (e.g. intensity value 0 in your case) and then just use findContours. Afterwards, for all contours, search (with cv::contourArea) the contour with the biggest area. This should give you the whole sky region in your sample image. – Micka Aug 24 '22 at 11:48
  • @Micka, Thank you for your suggestion. I am new to C++ OpenCV implementation, and OpenCV in general, so I am finding it a bit difficult to follow along. However, I will try what I know. If you could just provide a pseudo code, with the basic operations, it would make it much easier. Thanks once again – theboss12k Aug 24 '22 at 12:02
  • please replace the screenshots with the actual images. your screenshots of those imshow windows appear resampled. – Christoph Rackwitz Aug 24 '22 at 13:05
  • 2
    distance transform + your edge map: https://i.stack.imgur.com/1eCsx.png now, what do you think you'll find in the global maximum of the distance transform? the point that is furthest from any edge pixels, and its distance to the nearest one -- if you don't have to use C++, then ditch it. use python. nobody's prototyping in C++. – Christoph Rackwitz Aug 24 '22 at 13:10
  • @ChristophRackwitz, I have replaced the images with the images generated using `imwrite` function. – theboss12k Aug 24 '22 at 16:45
  • @ChristophRackwitz, Thank you so much for showing me how distance transform works with my edge map. However, is there any way find the area of the sky, or surround it using a box ? I am sorry if I sound dumb, but I am really new to image recognition and analysis. – theboss12k Aug 24 '22 at 16:55
  • @ChristophRackwitz, Agreed, in most places, python does make more sense than C++. But, my constraint is that the calculations and analysis has to be fast. I have read that Python is slower than C++ when it comes to calculations, and more particularly loops. That's why I chose C++ – theboss12k Aug 24 '22 at 16:57
  • you've been lied to. the functions called here are all compiled code, i.e. fast. even numpy operations are reasonably fast. python just calls them. *pure* python code is slow, but even that can be _compiled_ (numba) to be faster than numpy or other compiled libraries. "python is slow" is a lie teachers tell their students because they are too young to know and comprehend the whole truth. and then it gets propagated by the majority that never question what they're being told. – Christoph Rackwitz Aug 25 '22 at 04:56
  • @ChristophRackwitz, I think I know what to do. Could you please share how you used `distance transform`, as in the parameters used ? I guess that I could try that once and see. When I use `img3=cv2.distanceTransform(img4,cv2.DIST_L2,0)`, where img4 is the grayscale image, I am getting a large, white screen. Also, as per your suggestion, I switched to Python, and it is so much better :) – theboss12k Aug 26 '22 at 10:24

0 Answers0