I am triyng to get the 3 columns of a NumPy (RGB) array:
print px
[[[ 0 0 0]
[255 255 255]
[255 0 0]
[ 0 255 0]
[ 0 0 255]]]
print px[:,0]
print px[:,1]
print px[:,2]
[[0 0 0]]
[[255 255 255]]
[[255 0 0]]
but I would like to get the R, G and B like
[[0 255 255 0 0]]
[[0 255 0 255 0]]
[[0 255 0 0 255]]
Could you help me?
Thank you
Hugo
Your array px is three-dimensional: the first dimension has just a single element: the complete arrays containing rows and colums. The second dimension is rows, the third is colums. Therefore, to select a column, and have it embedded in the outermost dimension like you have, use the following:
>>> print px[:,:,0]
[[ 0 255 255 0 0]]
>>> print px[:,:,1]
[[ 0 255 0 255 0]]
>>> print px[:,:,2]
[[ 0 255 0 0 255]]
Related
This question already has an answer here:
How to count RGB or HSV channel combination in an image?
(1 answer)
Closed 2 years ago.
I need to output the number of pixels from an image
Hello guys, I need a hand to output the total number of pixels by color. I am new to image processing with Numpy and Numpy array. I know I need to have knowledge of it when I am dealing with individual pixel in image. I try to look for more resources about obtaining pixels value with Numpy. I couldn't find any helpful to my situation.Please help me. I am eager to learn more. Any documentation or blog post or books. Any comments highly appreciated.
I am trying to print like this:
red : ????? pixels
green : ??????? pixels
blue : ??? pixels
-------------------------
the image shape is (1536, 2048, 3)
I have tried this code
from PIL import Image
import numpy as np
img_path = "sample.png"
with Image.open(img_path) as im:
data = np.array(im)
red, green, blue = data[:, :, 0], data[:, :, 1], data[:, :, 2]
print(red, green, blue)
But it given me something like this
[[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]
...
[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]] [[255 255 255 ... 255 255 255]
[255 255 255 ... 255 255 255]
[255 255 255 ... 255 255 255]
...
[255 255 255 ... 255 255 255]
[255 255 255 ... 255 255 255]
[255 255 255 ... 255 255 255]] [[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]
...
[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]]
You could add this at the end.
print(np.count_nonzero(red))
print(np.count_nonzero(green))
print(np.count_nonzero(blue))
EDIT:
If you don't use single channel colors you could do something like this:
from PIL import Image
import numpy as np
img_path = "sample.png"
colors = {}
with Image.open(img_path) as im:
data = np.array(im)
for row in data:
for pixel in row:
color = '{}_{}_{}'.format(*pixel)
colors[color] = colors.get(color, 0)
colors[color] += 1
for color, count in colors.items():
print(color, count)
You can use np.count_nonzero, reducing along the two first axes, which will give you a count of pixels across the channels:
np.count_nonzero(im, axis=(0,1))
For instance:
from sklearn.datasets import load_sample_images
im = load_sample_images()['images'][0]
np.count_nonzero(im, axis=(0,1))
# array([272366, 272418, 268717], dtype=int64)
I am trying to write a white mask on a black, two-dimensional NumPy array — an image with one channel — in OpenCV using Python:
mask = np.zeros(shape=(100, 100), dtype=np.int8)
cv2.fillPoly(mask, np.array([[[0,0], [89, 0], [99,50], [33,96], [0,47]]], dtype=np.int32), color=255)
print(mask)
However, the polygon has a grey color when I print the mask:
[[127 127 127 ... 0 0 0]
[127 127 127 ... 0 0 0]
[127 127 127 ... 0 0 0]
...
[ 0 0 0 ... 0 0 0]
[ 0 0 0 ... 0 0 0]
[ 0 0 0 ... 0 0 0]]
I tried a 3D NumPy array with color=(255,255,255), I tried different colours, all to no avail. Why is it ignoring the color argument?
The problem comes from the initialization of your mask:
mask = np.zeros(shape=(100, 100), dtype=np.int8)
The value range of the int8 data type is -128 ... 127, thus any value above 127 will be "truncated" to 127.
Try your code with color=100, you'll get the expected output:
[[100 100 100 ... 0 0 0]
[100 100 100 ... 0 0 0]
[100 100 100 ... 0 0 0]
...
[ 0 0 0 ... 0 0 0]
[ 0 0 0 ... 0 0 0]
[ 0 0 0 ... 0 0 0]]
I guess, you wanted to use uint8 instead of int8, so maybe it's just a simple typo!?
Changing your code accordingly to
mask = np.zeros(shape=(100, 100), dtype=np.uint8)
then gives the expected result, also for color=255:
[[255 255 255 ... 0 0 0]
[255 255 255 ... 0 0 0]
[255 255 255 ... 0 0 0]
...
[ 0 0 0 ... 0 0 0]
[ 0 0 0 ... 0 0 0]
[ 0 0 0 ... 0 0 0]]
The problem lies in the datatype selection when initializing the numpy array. In your example code you are using np.int8 , which has a range from -128 ... 127.. Instead of np.int8 you should consider using np.uint8, which has a range of 0 ... 255, whixh you are looking for.
mask = np.zeros(shape=(100, 100), dtype=np.int8)
should be
mask = np.zeros(shape=(100, 100), dtype=np.uint8)
[[255 255 255 ... 0 0 0]
[255 255 255 ... 0 0 0]
[255 255 255 ... 0 0 0]
...
[ 0 0 0 ... 0 0 0]
[ 0 0 0 ... 0 0 0]
[ 0 0 0 ... 0 0 0]]
For me the problem was not initializing the mask with depth.
mask = np.zeros(shape = (MASK_WIDTH, MASK_HEIGHT), dtype=np.uint8)
Solved with this code
mask = np.zeros(shape = (MASK_WIDTH, MASK_HEIGHT, 3), dtype=np.uint8)
rcolor = list(np.random.random(size=3) * 256)
cv2.fillPoly(mask, [arr], color=rcolor)
cv2.imwrite(os.path.join(mask_folder, itr + ".jpg") , cv2.cvtColor(mask, cv2.COLOR_RGB2BGR))
I want to use the function cv2.connectedComponents to connect components on a binary image, like the following...
.
Everything works, except the outputted labels array. In this array are only zeros and not sequential numbers as indicated, according to the identified components.
import cv2
import numpy as np
img = cv2.imread('eGaIy.jpg', 0)
img = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)[1] # ensure binary
ret, labels = cv2.connectedComponents(img)
# Map component labels to hue val
label_hue = np.uint8(179*labels/np.max(labels))
blank_ch = 255*np.ones_like(label_hue)
labeled_img = cv2.merge([label_hue, blank_ch, blank_ch])
# cvt to BGR for display
labeled_img = cv2.cvtColor(labeled_img, cv2.COLOR_HSV2BGR)
# set bg label to black
labeled_img[label_hue==0] = 0
cv2.imshow('labeled.png', labeled_img)
cv2.waitKey()
outputted labels --> labels.shape: (256L, 250L)
[[0 0 0 ..., 0 0 0]
[0 0 0 ..., 0 0 0]
[0 0 0 ..., 0 0 0]
...,
[0 0 0 ..., 0 0 0]
[0 0 0 ..., 0 0 0]
[0 0 0 ..., 0 0 0]]
It works for me:
And you should be careful that the function only find the component of nonzero. In the source image, the components are the edges. And the returned are labeled image as the same size of source.
The output of
[[0 0 0 ..., 0 0 0]
[0 0 0 ..., 0 0 0]
[0 0 0 ..., 0 0 0]
...,
[0 0 0 ..., 0 0 0]
[0 0 0 ..., 0 0 0]
[0 0 0 ..., 0 0 0]]
only represent the 4 corner regions(3x3) are all zeros, but it doesn't mean all elements are zeros.
If you call this after you call the cv2.connectedComponents:
print(set(labels.reshape(-1).tolist()))
You will get:
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}
It means there exist 14 components(edges), and 1 background(0).
I have this array as a result of subtracting two images after getting there RGB integer values as an arrays
arr = img1 - img2
[[[0 0 0]
[0 0 0]
[0 0 0]
...,
[0 0 0]
[0 0 0]
[0 0 0]]
...,
[[0 0 0]
[0 0 0]
[0 0 0]
...,
[0 0 0]
[0 0 0]
[0 0 0]]]
i used these lines of code to change the shape of array to add the indices of each pixel subtraction
x, y, z = arr.shape
indices = np.vstack(np.unravel_index(np.arange(x*y), (y, x))).T
result = np.hstack((arr.reshape(x*y, z), indices))
and here what the result looks like:
[[ 0 0 0 0 0]
[ 0 0 0 0 1]
[ 0 0 0 0 2]
...,
[ 0 0 0 511 509]
[ 0 0 0 511 510]
[ 0 0 0 511 511]]
the first three values in each row is the RGB difference and the last two values is the X and Y indices
my question here, is there an efficient way to find the indices of the non zero values?
If I understand what you're saying correctly, you want them per list in your list of lists...
Saying this is your list:
l=[[0,0,0,0,0],[0,0,0,0,1],[0,0,0,0,2],[0,0,0,511,509],[0,0,0,511,510],[0,0,0,511,511]]
try running:
import numpy as np
ans=[np.nonzero(l[i])[0] for i in range(1,len(l))]
print ans
returns:
[array([4]), array([4]), array([3, 4]), array([3, 4]), array([3, 4])]
So it's an array containing arrays that have the indices of each non-zero element in each list. Since it uses list comprehension it runs pretty quickly and accession is as simple as using the indices. It will just be ans[list in list of lists][number of non-zero indices] like so:
ans[2][1]
4
I'm just starting to use OpenCV with Python and am trying to do some simple things. To start with, I tried to create a solid Blue image (or possibly Red, if the image turns out to be RGB, instead of BGR).
I tried the following:
import numpy as np
import cv2
img1 = np.zeros((512,512,3), np.uint8) #Create black image
img1[0,:,:] = 200 #Add intenstity to blue (red?) plane
print img1 #Verify image array
cv2.imshow("II",img1)
cv2.waitKey(0)
cv2.destroyAllWindows()
for _ in range (1,5):
cv2.waitKey(1)
But, what I got was a black image. I'm fairly certain the array was correct, because the print statement gave me the following:
[[[200 200 200]
[200 200 200]
[200 200 200]
...,
[200 200 200]
[200 200 200]
[200 200 200]]
[[ 0 0 0]
[ 0 0 0]
[ 0 0 0]
...,
[ 0 0 0]
[ 0 0 0]
[ 0 0 0]]
[[ 0 0 0]
[ 0 0 0]
[ 0 0 0]
...,
[ 0 0 0]
[ 0 0 0]
[ 0 0 0]]
...,
[[ 0 0 0]
[ 0 0 0]
[ 0 0 0]
...,
[ 0 0 0]
[ 0 0 0]
[ 0 0 0]]
[[ 0 0 0]
[ 0 0 0]
[ 0 0 0]
...,
[ 0 0 0]
[ 0 0 0]
[ 0 0 0]]
[[ 0 0 0]
[ 0 0 0]
[ 0 0 0]
...,
[ 0 0 0]
[ 0 0 0]
[ 0 0 0]]]
Does it make sense that I'm seeing a black instead of a blue (or red?) image?
What you're doing is changing color of 0th row. Instead, you need to change the values of first or 0th channel.
img[:, :, 0] = 255
This will change all the values of first or 0th channel to 255 which would give you blue image as it is a BGR Image.
You need to specify the colors as a tuple ! if you want a RGB image because very Index in array is a pixel and you need 3 value for B,G,R ( opencv set the pixels as BGR)
import numpy as np
import cv2
img1 = np.zeros((512,512,3), np.uint8) #Create black image
img1[:,:] = (255,0,0) #Add intenstity to blue (red?) plane
print img1 #Verify image array
cv2.imshow("II",img1,)
cv2.waitKey(0)
cv2.destroyAllWindows()
for _ in range (1,5):
cv2.waitKey(1)
result: