0

I'm working on an Image Processing Algorithm that involves placing a mask on an image and hiding certain regions as follows,

Image 1

Image 1

Image 1 Reduced

Image 2

Visually Image 1 has undergone a reduction of about 50%.

Some of the images I work with also end up having isolated regions like the one below.

Image 3

To compute reduction in the image I used the following code to calculate the increase in black pixels,

sought = [0,0,0]
black1  = np.count_nonzero(np.all(Image1==sought,axis=2)) #Black pixels in Image 1
black2  = np.count_nonzero(np.all(Image1_reduced==sought,axis=2)) #Black pixels in Image 1 Reduced

reduction = ((black2-black1)/black1)*100

print("Reduction %: ", round(reduction, 2))

However the code block shows erroneous values for reduction. Are there any alternatives to this approach?

The Singularity
  • 2,428
  • 3
  • 19
  • 48
  • erroneous how? are you sure your calculation is correct? please provide a self-contained example (literal values in an array instead of whole pictures if possible) – Christoph Rackwitz Dec 28 '20 at 11:55
  • you realize that both of your images already contain a lot of black, and that affects your calculation. just take the picture's size into account as well. – Christoph Rackwitz Dec 28 '20 at 11:58
  • @ChristophRackwitz I'm unsure if my calculation is correct. Erroneous as in visually the images appear to have a 50% reduction while the code says around 30% – The Singularity Dec 28 '20 at 12:45

1 Answers1

0

You have to put the total number of pixels in the denominator instead of the number of black pixels.

In [161]: import numpy as np

In [162]: sought = [0, 0, 0]

In [163]: rows = cols = 256

In [164]: original = np.random.randint(
     ...:     low=0, high=256, size=(rows, cols, 3), dtype=np.uint8)
     ...: original[:rows//4, :, :] = sought

In [165]: masked = original.copy()
     ...: masked[:, :cols//4, :] = sought

In [166]: black1 = np.count_nonzero((original == sought).all(axis=-1))

In [167]: black2 = np.count_nonzero((masked == sought).all(axis=-1))

In [168]: import matplotlib.pyplot as plt
     ...: fig, (ax0, ax1) = plt.subplots(1, 2)
     ...: ax0.imshow(original)
     ...: ax0.set_title('Original')
     ...: ax1.imshow(masked)
     ...: ax1.set_title('Masked')
     ...: plt.show(fig)

mock data

In [169]: reduction = 100*(black2 - black1)/(rows*cols)

In [170]: print(f'Reduction = {reduction:.2f}%')
Reduction = 18.75%

In the example above the increase of black pixels is 1/4 - 1/16 which equals 0,1875.


Edit

Maybe that "the images visually seem to have about 50% reduction", but the reduction is actually 36.61%. Run this code to convince yourself.

In [192]: from skimage import io

In [193]: original = io.imread('https://i.stack.imgur.com/PwVmP.png')

In [194]: masked = io.imread('https://i.stack.imgur.com/OG2aF.png')

In [195]: non_black_pixels_1 = np.logical_not((original == sought).all(axis=-1))

In [196]: black_pixels_2 = (masked == sought).all(axis=-1)

In [197]: new_black_pixels = np.logical_and(black_pixels_2, non_black_pixels_1)

In [198]: import matplotlib.pyplot as plt
     ...: fig, (ax1, ax2, ax3) = plt.subplots(1, 3)
     ...: ax1.imshow(original)
     ...: ax1.set_title('Image 1')
     ...: ax2.imshow(masked)
     ...: ax2.set_title('Image 1 Reduced')
     ...: ax3.imshow(new_black_pixels)
     ...: ax3.set_title('New black pixels')
     ...: plt.show(fig)

real examples

In [199]: reduction = 100*new_black_pixels.mean()

In [200]: print(f'Reduction = {reduction:.2f}%')
Reduction = 36.61%

Edit #2

As per the comments, it seems that you are trying to compute the percentage of non-black pixels that become black after masking. The following snippet does exactly that:

In [219]: nonblack1 = np.count_nonzero((original != sought).any(axis=-1))

In [220]: nonblack2 = np.count_nonzero((masked != sought).any(axis=-1))

In [221]: reduction = 100*(nonblack1 - nonblack2)/nonblack1

In [222]: print(f'Reduction = {reduction:.2f}%')
Reduction = 55.85%
Tonechas
  • 13,398
  • 16
  • 46
  • 80
  • The method you provided seems logical but does not appear to work in my case. I get the following values for Image 1: black1: 21275, black2: 43879, rows: 246, cols: 251 with a reduction of 36.61% which appears to be incorrect as the images visually seem to have about 50% reduction. I've also tried your method on other images but erroneous values still show up. – The Singularity Dec 28 '20 at 12:58
  • Could you share the images? – Tonechas Dec 28 '20 at 13:01
  • The question is updated and now contains the original images (Image 1 and Image 1 Reduced) – The Singularity Dec 28 '20 at 13:10
  • Perharps you want to compute the percentage of *non-black* pixels in the original image that become black after masking. Is that assumption correct? – Tonechas Dec 28 '20 at 17:33
  • The approach we've taken seems to be logically correct but my objectives aren't met yet. Here's a [reference](https://stackoverflow.com/questions/65454717/calculating-percentage-of-image-overlap) to what I'm actually trying to achieve – The Singularity Dec 29 '20 at 08:11
  • We have apparently computed a reduction of 36.61% for the entire 246 x 251 image rather than just the colored image. – The Singularity Dec 29 '20 at 08:15