How to verify if a pixel is above another

Question:

What is the best way to know the amount of white pixels that are anove the red areas using python and OpenCV?

enter image description here

I imagine drawing a straight vertical line from each white pixel to height Y = 512 might be one of the ways, but I have no idea how to make that happen

Asked By: user20372455

||

Answers:

If I understood it well, what you want is to, for every white pixel (even those in the same x coordinate) cast a ray downwards and count how many of them intersects those red lake thingy, right?

If so, only numpy should be enough. Imagine applying gravity to white pixels, making them fall to the ground and counting the height of each column, multiplied by a 1D-bool-array of columns containing red pixels:

What I mean is, you can reshape the image from 2D to 1D, becoming essentially a histogram/array of how many white pixels a given column had (Int 1D-Array), using np.sum(a,axis=0) after removing non-white pixels. You can apply the same to red pixels, but not to count them, just to check whether a column had a red pixel or not (bool 1D-Array). Multiply those 2 arrays together and you will have another array of just intersecting pixels.

[EDIT]:
Something like this pseudo-code:

import numpy as np
from PIL import Image

img_obj = Image.open('test.jpg')  # assuming you're opening the image from a file, and using Pillow.
img_arr = np.array(img_obj)  # This creates a 3D array (width, height, rgb. Like 512x512x3)

# This creates a 2D boolean array, 512x512x1. But watch it, some pixels might not be precisely 255.
white_pixels = img_arr[:,:,0] == 255 and img_arr[:,:,1] == 255 and img_arr[:,:,2] == 255
red_pixels = img_arr[:,:,0] == 255 and img_arr[:,:,1] == 0 and img_arr[:,:,2] == 0

white_columns = np.sum(white_pixels, axis=0)  # This could be axis=1, not sure.
red_columns = np.sum(red_pixels, axis=0) > 0  # We just need booleans telling the presence of red in the column.

intersecting_columns = white_columns * red_columns
raycast_hits_count = np.sum(intersecting_columns)

There will probably be a few conversion errors like casting int to boolean, or pixel values being floats between 0 and 1, stuff like that. But the core concept is this

Answered By: Emanuel Kozerski

I would do that like this, showing all steps along the way:

#!/usr/bin/env python3

import numpy as np
import cv2

# Load image
im = cv2.imread('R5qoS.png')

# Make a True/False mask of white pixels and save for debug
white = np.all(im==[255,255,255], axis=2)
cv2.imwrite('DEBUG-white.png', white*255)

# Make a True/False mask of red pixels and save for debug
red = np.all(im==[0,0,255], axis=2)
cv2.imwrite('DEBUG-red.png', red*255)

# Get all columns with red pixels in them
colsWithRed = np.argwhere(np.any(red==True, axis=0))
print(f'colsWithRed: {colsWithRed}')

# Get all columns with white pixels in them
colsWithWhite = np.argwhere(np.any(white==True, axis=0))
print(f'colsWithWhite: {colsWithWhite}')

# Get all columns with red and white
both = np.intersect1d(colsWithWhite,colsWithRed)
print(f'Columns with white and red: {both}')

DEBUG-white.png

enter image description here

DEBUG-red.png

enter image description here

Output

Columns with white and red: [142 143 144 148 149 150 151 152 153 154 155 156 157 349 350 351 387 388 389 399 400 401]

Note: axis=0 means "looking down the columns". axis=1 means "looking along the rows". axis=2 means "looking across the BGR/RGB colour channels".

Answered By: Mark Setchell
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.