Add two 3D numpy arrays with a 2D mask - python

I would like to add two 3D numpy arrays (RGB image arrays) with a 2D mask generated by some algorithms on a greyscale image. What is the best way to do this?
As an example of what I am trying to do:
from PIL import Image, ImageChops, ImageOps
import numpy as np
img1=Image.open('./foo.jpg')
img2=Image.open('./bar.jpg')
img1Grey=ImageOps.grayscale(img1)
img2Grey=ImageOps.grayscale(img2)
# Some processing for example:
diff=ImageChops.difference(img1Grey,img2Grey)
mask=np.ma.masked_array(img1,diff>1)
img1Array=np.asarray(im1)
img2Array=np.asarray(im2)
imgResult=img1Array+img2Array[mask]
I was thinking:
1) break up the RGB image and do each color separately
2) duplicate the mask into a 3D array
or is there a more pythonic way to do this?
Thanks in advance!

Wish I could add a comment instead of an answer. Anyhow:
masked_array is not for making masks. It's for including only the data outside the mask in calculations such as sum, mean, etc.. scientific statistical applications. It's comprised of an array and the mask for the array.
It's probably NOT what you want.
You probably just want a normal boolean mask, as in:
mask = diff>1
Then you'll need to modify the shape so numpy broadcasts in the correct dimension, then broadcast it into the 3rd dimension:
mask.shape = mask.shape + (1,)
mask = np.broadcast_arrays(img1Array, mask)[1]
After that, you can just add the pixels:
img1Array[mask] += img2Array[mask]
A further point of clarification:
imgResult=img1Array+img2Array[mask]
That could never work. You are saying 'add some of the pixels from img2Array to all of the pixels in img1Array' 6_9
If you want to apply a ufunc between two or more arrays, they must be either the same shape, or broadcastable to the same shape.

Related

how can i make mask image bigger with python numpy?

I have array that represent a mask with shape (3080, 2000) and dtype('uint8'),
the following picture
[mask image ][1]
my mask is not always a rectangle could be any shape, I just want to make the mask bigger, I mean to extend it a few pixels in every direction how can I achieve that.
[1]: https://i.stack.imgur.com/K2zaA.png

Replace certain pixels by integers in numpy array

I have made myself a numpy array from a picture using
from PIL import Image
import numpy as np
image = Image.open(file)
np.array(image)
its shape is (6000, 6000, 4) and in that array I would like to replace pixel values by one number lets say this green pixel [99,214,104,255] will be 1.
I have only 4 such pixels I want to replace with a number and all other pixels will be 0. Is there a fast and efficient way to do so and what is the best way to minimize the size of the data. Is it better to save it as dict(), where keys will be x,y and values, will be integers? Or is it better to save the whole array as it is with the shape it has? I only need the color values the rest is not important for me.
I need to process such a picture as fast as possible because there is one picture every 5 minutes and lets say i would like to store 1 year of data. That is why I'd like to make it as efficient as possible time and space-wise.
If I understand the question correctly, you can use np.where for this:
>>> arr = np.array(image)
>>> COLOR = [99,214,104,255]
>>> np.where(np.all(arr == COLOR, axis=-1), 1, 0)
This will produce a 6000*6000 array with 1 if the pixel is the selected colour, or 0 if not.
How about just storing in a database: the position and value of the pixels you want to modify, the shape of the image, the dtype of the array and the extension (jpg, etc...). You can use that information to build a new image from an array filled with 0.

Creating numpy masked array on 3 channel array never works

I have a 3 channel numpy array, ie an image and I want to mask out some areas then calculate the mean on the unmasked areas. When I go to convert my numpy array to a masked numpy array I always get the following error:
raise MaskError(msg % (nd, nm))
numpy.ma.core.MaskError: Mask and data not compatible: data size is 325080, mask size is 108360.
My array (image) shape is: (301, 360, 3) for reference. I create my mask by creating a duplicate array of zeros then drawing a polygon shape of 1's (True) on the mask.
My code is:
mask = np.zeros((src.shape[0], src.shape[1], 1), dtype='uint8')
cv2.drawContours(mask, [np.array(poly)], -1, (1,), -1)
msrc = np.ma.array(src, mask=mask, dtype='uint8') # error on this line
mean = np.ma.mean(msrc)
What am I doing wrong and how can I fix it to successfully create a masked array in numpy?
As stated in the comments, numpy doesn't consider images, it's just math. OpenCV abstracts that math into easy image manipulations.
To mask an image using OpenCV, you can use
masked_img = cv2.bitwise_and(src,src,mask=mask).
(docs)

Swapping array dimensions with NumPy

When I load an image with PIL and convert it into a NumPy array:
image = Image.open("myimage.png")
pixels = np.asarray(image)
The data is stored as [x][y][channel]. I.e., the value of pixels[3, 5, 0] will be the the (3, 5) pixel, and the red component of that pixel.
However, I am using a library which requires the image to be in the format [channel][x][y]. Therefore, I am wondering how I can do this conversion?
I know that NumPy has a reshape function, but this doesn't actually allow you to "swap" over the dimensions as I want.
Any help? Thanks!
In order to get the dimensions in the order that you want, you could use the transpose method as follows:
image = Image.open("myimage.png")
pixels = np.asarray(image).transpose(2,0,1)

Reordering numpy array indices

I have a 2D array that I want to create an image from. I want to transform the image array of dimensions 140x120 to an array of 140x120x3 by stacking the same array 3 times (to get a grayscale image to use with skimage).
I tried the following:
image = np.uint8([image, image, image])
which results in a 3x120x140 image. How can I reorder the array to get 120x140x3 instead?
np.dstack([image, image, image]) (docs) will return an array of the desired shape, but whether this has the right semantics for your application depends on your image generation library.

Categories