iam trying to generate images and train a neural network,
i make these images via making an empty np array
image = np.empty((400, 400), np.int32) to make the shape on it
image = cv2.circle(image, (CordX, CordY), rad, color, thickness)
I don't know how to make it 3 dimensional (image.shape op currently is 400, 400) and the output should be 400, 400, 3
To convert gray image to RGB, you can simply repeat one channel 3 times:
# Create additional axis
image = image[:, :, None]
print(image.shape) # (400, 400, 1)
# Repeat 3 times along axis 2
image = image.repeat(3, 2)
print(image.shape) # (400, 400, 3)
Full example:
image = np.empty((400, 400), np.int32)
image = cv2.circle(image, (200, 200), 20, 100, 3)
image = image[:, :, None].repeat(3, 2)
import matplotlib.pyplot as plt
plt.imshow(image)
plt.show()
Alternatively, you could create RGB image in the first place:
image = np.empty((400, 400, 3), np.int32)
image = cv2.circle(image, (200, 200), 20, (100, 100, 100), 3)
This is the same image as above.
Related
I wanted to create a blank alpha image to parse some data from py-opencv and save it on an transparent background png file.
I tried :
blank_image = np.zeros((H,W,4), np.uint8)
and
blank_image = np.full((H, W, 4) , (0, 0, 0, 0), np.uint8)
(H and W are Height and Width)
Both still render a black background instead of a transparent one.
how to get a blank alpha transparent image?
Thanks in advance :)
Edits:
as mentioned by Mark Setchell: you need to specify the alpha channel on other colors involved:
# size of the image
(H , W) = 1080, 1080
# Blank image with RGBA = (0, 0, 0, 0)
blank_image = np.full((H, W, 4), (0, 0, 0, 0), np.uint8)
# Green color with Alpha=255
RGBA_GREEN = (0, 255, 0, 255)
# Opencv element using the RGBA color
cv2.putText(blank_image, 'my opencv element', (20 , 20), cv2.FONT_HERSHEY_SIMPLEX, 0.5, RGBA_GREEN, 2)
cv2.imwrite('image_alpha.png', blank_image)
You need to make the alpha channel = 255 to see anything.
import numpy as np
H, W = 128, 256
blank_image = np.zeros((H,W,4), np.uint8)
# Make first 10 rows red and opaque
blank_image[:10] = [255,0,0,255]
# Make first 10 columns green and opaque
blank_image[:,:10] = [0,255,0,255]
You can also make your RGB image as you wish, then create an alpha layer entirely separately and add it afterwards:
# Make solid red image
RGB = np.full((H, W, 3) , (255, 0, 0), np.uint8)
# Make a gradient alpha channel, left-to-right, 0..255
alpha = np.repeat(np.arange(256,dtype=np.uint8)[np.newaxis,:], 128, axis=0)
# Apply alpha to RGB image to yield RGBA image
RGBA = np.dstack((RGB,alpha))
I am loading an image using OpenCV python as a greyscale image because of which the shape of the image is (125, 125). But, I need the shape to be (125, 125, 1) where 1 denotes the number of channels ( 1 since it's greyscale ).
img = cv2.imread('/path/to/image.png', 0)
print(img.shape)
# prints (125, 125)
Now, I need to convert img's shape to (125, 125, 1)
The easiest way is to use numpy indexing and np.newaxis:
img = np.ones((125, 125)) # img.shape: (125, 125)
img_3d = img[..., np.newaxis] # img_3d.shape: (125, 125, 1)
This is especially handy if you only need the extra dimensions to pass the data to another function, so you can just pass the fancy-indexed array.
Try np.expand_dims:
In [1]: import numpy as np
In [2]: img = np.ones((125, 125))
In [3]: img.shape
Out[3]: (125, 125)
In [4]: img = np.expand_dims(img, axis=-1)
In [5]: img.shape
Out[5]: (125, 125, 1)
import numpy as np
a = np.random.rand(5,5)
b = a.reshape(5,5,1)
b = a.reshape(1,5,5)
b = a.reshape(1,5,5,1)
any shape you want
I want to get the histogrm of a region in a numpy image in python. I found a solution on how to use a mask here.
this solution didnt help me because if i use it I will loose the real number of black pixels. Also, the region that i want to get is not necessarly rectangular.
To compute histogram use np.histogram function. It returns a histogram and bins. So you can store the results and work with it:
hist, bins = np.histogram(arr, bins=bins, range=range)
If you want to plot the results, you can use plt.bar after applying np.histogramsimply passing bins and hist:
plt.bar(bins, hist)
Another option is using matplotlib plt.hist it computes the histogram and plots it from a raw data:
plt.hist(arr, bins=bins)
Here is the complete example for the histogram of image region of any shape:
Code:
import numpy as np
import matplotlib.pyplot as plt
from scipy.misc import face
from PIL import Image, ImageDraw
# Let's create test image with different colors
img = np.zeros((300, 300, 3), dtype=np.uint8)
img[0:150, 0:150] = [255, 0, 0]
img[0:150, 150:] = [0, 255, 0]
img[150:, :150] = [0, 0, 255]
img[150:, 150:] = [255, 255, 255]
# define our function for preparing mask
def prepare_mask(polygon, image):
"""Returns binary mask based on input polygon presented as list of coordinates of vertices
Params:
polygon (list) - coordinates of polygon's vertices. Ex: [(x1,y1),(x2,y2),...] or [x1,y1,x2,y2,...]
image (numpy array) - original image. Will be used to create mask of the same size. Shape (H, W, C).
Output:
mask (numpy array) - boolean mask. Shape (H, W).
"""
# create an "empty" pre-mask with the same size as original image
width = image.shape[1]
height = image.shape[0]
mask = Image.new('L', (width, height), 0)
# Draw your mask based on polygon
ImageDraw.Draw(mask).polygon(polygon, outline=1, fill=1)
# Covert to np array
mask = np.array(mask).astype(bool)
return mask
def compute_histogram(mask, image):
"""Returns histogram for image region defined by mask for each channel
Params:
image (numpy array) - original image. Shape (H, W, C).
mask (numpy array) - boolean mask. Shape (H, W).
Output:
list of tuples, each tuple (each channel) contains 2 arrays: first - computed histogram, the second - bins.
"""
# Apply binary mask to your array, you will get array with shape (N, C)
region = image[mask]
red = np.histogram(region[..., 0].ravel(), bins=256, range=[0, 256])
green = np.histogram(region[..., 1].ravel(), bins=256, range=[0, 256])
blue = np.histogram(region[..., 2].ravel(), bins=256, range=[0, 256])
return [red, green, blue]
def plot_histogram(histograms):
"""Plots histogram computed for each channel.
Params:
histogram (list of tuples) - [(red_ch_hist, bins), (green_ch_hist, bins), (green_ch_hist, bins)]
"""
colors = ['r', 'g', 'b']
for hist, ch in zip(histograms, colors):
plt.bar(hist[1][:256], hist[0], color=ch)
# Create some test masks
red_polygon = [(50, 100), (50, 50), (100, 75)]
green_polygon = [(200, 100), (200, 50), (250, 75)]
blue_polygon = [(50, 250), (50, 200), (100, 225)]
white_polygon = [(200, 250), (200, 200), (250, 225)]
polygons = [red_polygon, green_polygon, blue_polygon, white_polygon]
for polygon in polygons:
mask = prepare_mask(polygon, img)
histograms = compute_histogram(mask, img)
# Let's plot our test results
plt.figure(figsize=(10, 10))
plt.subplot(221)
plt.imshow(img)
plt.title('Image')
plt.subplot(222)
plt.imshow(mask, cmap='gray')
plt.title('Mask')
plt.subplot(223)
plot_histogram(histograms)
plt.title('Histogram')
plt.show()
Output:
The final test on raccoon:
Code:
raccoon = face()
polygon = [(200, 700), (150, 600), (300, 500), (300, 400), (400, 500)]
mask = prepare_mask(polygon, raccoon)
histograms = compute_histogram(mask, raccoon)
plt.figure(figsize=(10, 10))
plt.subplot(221)
plt.imshow(raccoon)
plt.title('Image')
plt.subplot(222)
plt.imshow(mask, cmap='gray')
plt.title('Mask')
plt.subplot(223)
plot_histogram(histograms)
plt.title('Histogram')
plt.show()
Output:
Let's define (x,y)coordinates of 5 points (p0, p1, p2, p3, p4) as the corners of the region. We can make a mask using opencv fillPoly function after concatinating the points as np array. The pixel values of image can be filtered with this mask. I use matplotlib's histogram. Opencv and numpy have also histogram functions.
import cv2
import numpy as np
from matplotlib import pyplot as plt
img_x = img.copy()
pts = np.concatenate((p0, p1, p2, p3, p4)).reshape((-1, 1, 2))
cv2.fillPoly(img_x , [pts], (255, 255, 255))
n, bins, patches = plt.hist(img[img_x == (255, 255, 255)], 256, [0, 256])
I want to use paste of the python PIL library to paste a image to a black background.
I know I can use the image itself as a alpha mask, but I only want to have the parts of the image where the alpha value is 255.
How is this possible?
Here is my code so far:
import PIL
from PIL import Image
img = Image.open('in.png')
background = Image.new('RGBA', (825, 1125), (0, 0, 0, 255))
offset = (50, 50)
background.paste(img, offset, img) #image as alpha mask as third param
background.save('out.png')
I can't find anything in the official but bad documentation
If I understand your question correctly, then
this is a possible solution. It generates
a dedicated mask, which is used for the paste:
from PIL import Image
img = Image.open('in.png')
# Extract alpha band from img
mask = img.split()[-1]
width, height = mask.size
# Iterate through alpha pixels,
# perform desired conversion
pixels = mask.load()
for x in range(0, width):
for y in range(0, height):
if pixels[x,y] < 255:
pixels[x,y] = 0
# Paste image with converted alpha mask
background = Image.new('RGBA', (825, 1125), (0, 0, 0, 255))
background.paste(img, (50, 50), mask)
background.save('out.png')
As a note, the alpha channel of the background image is fairly useless.
If you don't need it later on, you could also load the background with:
background = Image.new('RGB', (825, 1125), (0, 0, 0))
I have two images, both with alpha channels. I want to put one image over the other, resulting in a new image with an alpha channel, just as would occur if they were rendered in layers. I would like to do this with the Python Imaging Library, but recommendations in other systems would be fantastic, even the raw math would be a boon; I could use NumPy.
This appears to do the trick:
from PIL import Image
bottom = Image.open("a.png")
top = Image.open("b.png")
r, g, b, a = top.split()
top = Image.merge("RGB", (r, g, b))
mask = Image.merge("L", (a,))
bottom.paste(top, (0, 0), mask)
bottom.save("over.png")
Pillow 2.0 now contains an alpha_composite function that does this.
img3 = Image.alpha_composite(img1, img2)
I couldn't find an alpha composite function in PIL, so here is my attempt at implementing it with numpy:
import numpy as np
from PIL import Image
def alpha_composite(src, dst):
'''
Return the alpha composite of src and dst.
Parameters:
src -- PIL RGBA Image object
dst -- PIL RGBA Image object
The algorithm comes from http://en.wikipedia.org/wiki/Alpha_compositing
'''
# http://stackoverflow.com/a/3375291/190597
# http://stackoverflow.com/a/9166671/190597
src = np.asarray(src)
dst = np.asarray(dst)
out = np.empty(src.shape, dtype = 'float')
alpha = np.index_exp[:, :, 3:]
rgb = np.index_exp[:, :, :3]
src_a = src[alpha]/255.0
dst_a = dst[alpha]/255.0
out[alpha] = src_a+dst_a*(1-src_a)
old_setting = np.seterr(invalid = 'ignore')
out[rgb] = (src[rgb]*src_a + dst[rgb]*dst_a*(1-src_a))/out[alpha]
np.seterr(**old_setting)
out[alpha] *= 255
np.clip(out,0,255)
# astype('uint8') maps np.nan (and np.inf) to 0
out = out.astype('uint8')
out = Image.fromarray(out, 'RGBA')
return out
For example given these two images,
img1 = Image.new('RGBA', size = (100, 100), color = (255, 0, 0, 255))
draw = ImageDraw.Draw(img1)
draw.rectangle((33, 0, 66, 100), fill = (255, 0, 0, 128))
draw.rectangle((67, 0, 100, 100), fill = (255, 0, 0, 0))
img1.save('/tmp/img1.png')
img2 = Image.new('RGBA', size = (100, 100), color = (0, 255, 0, 255))
draw = ImageDraw.Draw(img2)
draw.rectangle((0, 33, 100, 66), fill = (0, 255, 0, 128))
draw.rectangle((0, 67, 100, 100), fill = (0, 255, 0, 0))
img2.save('/tmp/img2.png')
alpha_composite produces:
img3 = alpha_composite(img1, img2)
img3.save('/tmp/img3.png')