-1

I would like to use OpenCV to detect which rectangles in an image have a majority of pixels close to a given color.

Here's an example of an image I would like to process using this to identify rectangular regions that contain mostly gray pixels (possibly roads):

looking for roads

More precisely, given:

  • dimensions h x w (height and weight of candidate rectangles)
  • a distance function dist for colors (for example, the norm of the vector difference between the color vector, which could be RGB or any other representation)
  • a color vector C
  • a maximum distance d for colors to be from C
  • a minimum percentage rate r of pixels in a given rectangle to be within distance d from C for the rectangle to be of interest,

return a mask M in which each pixel P is 1 if the rectangle of size h x w left-cornered by P contains at least r % of its pixels within distance d from C when measured with dist.

In pseudo-code, pixel P in the mask is 1 if and only if:

def rectangle_left_cornered_at_P_is_of_interest(P):
    n_pixels_near_C = size([P' for P' in rectangle(P, P + (h,w)) if dist(P',C) < d])
    return n_pixels_near_C / (h * w) > r

I imagine there may already exist a filter/kernel that does just that (or can be used to do that) in OpenCV, but I am still learning about it and could not identify one by looking at the documentation. Is there such a thing?

user118967
  • 4,895
  • 5
  • 33
  • 54
  • 1
    This is a very broad question. What have you tried? What about it isn't working? What is your definition of the "distance" between colors? What color space are you working in, RGB, HSV, etc? Post some code and we might be able to help. – Fiver Aug 28 '19 at 22:22
  • Thanks. I have not tried anything yet. That was the point: I was trying to find out what OpenCV offers in this regard, so I can try something. I have defined the problem now in a more complete and precise mathematical fashion. – user118967 Aug 28 '19 at 23:10
  • can you provide an example image. – Andy_101 Aug 29 '19 at 06:49
  • @Andy_101, I've just added an example image. Thanks. – user118967 Aug 30 '19 at 05:41

1 Answers1

1

You can use HSV for this . you may have to play with the values a bit for the mask but it will get the job done.

img = cv2.imread(img)
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

lower_gray = np.array([0, 5, 50], np.uint8)
upper_gray = np.array([350, 50, 255], np.uint8)

mask = cv2.inRange(hsv, lower_gray, upper_gray)
img_res = cv2.bitwise_and(img, img, mask = mask)
cv2.imwrite('gray.png',img_res)

You should also refer to this post. Its a good post on the use of HSV.

Basicly all you will need for this job will be : HSV masks, Otsu thresholding , blurs and may be erosion and dilation.

Use them in some combition that fits your requirement best.

Andy_101
  • 1,246
  • 10
  • 20
  • Thank you. That helps with detecting gray, but it does not help with determining which rectangles with a certain height and width have a minimum percentage of gray pixels. To do that, I would have to write a loop over all pixels and another nested loop to analyze all the neighboring pixels in the respective rectangle, but that would be too slow in Python, so that is why I was hoping for some kind of OpenCV filter or kernel that operated on the C level. – user118967 Aug 30 '19 at 21:05