4

I am trying to select an area of an image to do some analysis on that specific area of the image.

However, when I searched online, I am only able to find guides on how to select a rectangular area. I need to select an area that is drawn using my mouse. An example of such area is included bellow.

Would anyone be able to recommend to me some key words or libraries to search to help me with this or links to guides that do something similar?

Also, I am not sure if it is necessary information but the analysis I am trying to do on the region of interest is to Find a ratio of amount of white to black pixels in that specific area.

Example of an area I am trying to select

Ruven Guna
  • 414
  • 7
  • 25
  • Is this always a fully closed area? I.e., is there at least one pixel connected in the 8-neighborhood of the image? – dennlinger Aug 07 '18 at 06:34
  • @dennlinger It will always be fully enclosed. I am not too sure what you mean by the second question, but this ROI is in the middle of the image. Thanks! – Ruven Guna Aug 07 '18 at 06:37
  • The 8-neighborhood simply specifies the surrounding pixels of a pixel (left, upper-left, upper, upper-right, right, lower-right, lower, lower-left), instead of a 4-neighborhood (left, upper, right, lower). – dennlinger Aug 07 '18 at 06:45
  • @dennlinger I think I understand what you mean. Yes, there is at least one pixel connected in the 8-neighborhood of the image. Thank you. – Ruven Guna Aug 07 '18 at 06:50

1 Answers1

1

I produced a simple working example based on this answer. I also tried using scipy.ndimage.morphology.fill_binary_holes, but could not get it to work. Note that the provided function takes a little longer since it is assuming that the input image is grayscale and not binarized.

I specifically avoided the usage of OpenCV, since I find the setup to be a bit tedious, but I think it should also provide an equivalent (see here).

Additionally, my "binarization" is kind of hacky, but you can probably figure out how to parse your image into a valid format yourself (and it might be easier if you produce the result within a program). In any case, I would suggest making sure that you have a proper image format, since jpeg's compression might violate your connectivity, and cause issues in certain cases.

import scipy as sp
import numpy as np
import scipy.ndimage
import matplotlib.pyplot as plt

def flood_fill(test_array,h_max=255):
    input_array = np.copy(test_array) 
    el = sp.ndimage.generate_binary_structure(2,2).astype(np.int)
    inside_mask = sp.ndimage.binary_erosion(~np.isnan(input_array), structure=el)
    output_array = np.copy(input_array)
    output_array[inside_mask]=h_max
    output_old_array = np.copy(input_array)
    output_old_array.fill(0)   
    el = sp.ndimage.generate_binary_structure(2,1).astype(np.int)
    while not np.array_equal(output_old_array, output_array):
        output_old_array = np.copy(output_array)
        output_array = np.maximum(input_array,sp.ndimage.grey_erosion(output_array, size=(3,3), footprint=el))
    return output_array

x = plt.imread("test.jpg")
# "convert" to grayscale and invert
binary = 255-x[:,:,0]

filled = flood_fill(binary)

plt.imshow(filled)

This produces the following result: final result

dennlinger
  • 9,890
  • 1
  • 42
  • 63