I need to stack two images with the same width to create a new image.
I currently have two images which are slices of the same image:
img is the name of the original image with shape (480, 640, 3)
timestamp = img[:40, :200, :]
variables = img[370:, :200, :]
I either want to stack these images somehow or slice the original image in such a way that I take the first 40 pixels and the last 90 pixels (as above)
Thanks in advance!
You can use np.vstack:
new_img = np.vstack([img[:40, :200, :], img[370:, :200, :]])
Related
I have a multiple pictures with different dimensions. I have been trying to concat them horizontally using openCV.
The process is kind of following:
Iterate over all the images to find the max width and total height.
Create a black mask that is with the size of max width and total height got from all the images.
Stack all the images horizontally on that black mask.
I am not sure how to do this thing. Kindly help me!
Images are just 3D matrices, so you can do this very easily by creating a matrix of zeros (= black) of the desired size, then filling in your images.
I've created fake images here but you can use cv2 to read in your real images.
import numpy as np
import matplotlib.pyplot as plt
# create three images of different shapes and different shades of grey
img1 = np.ones((100, 200, 3), dtype=int)*50
img2 = np.ones((200, 400, 3), dtype=int)*100
img3 = np.ones((100, 300, 3), dtype=int)*150
imgs = [img1, img2, img3]
# get max width and total height
max_width = 0
total_height = 0
for img in imgs:
total_height += img.shape[0]
max_width = max(max_width, img.shape[1])
# make black canvas of appropriate shape
canvas = np.zeros((total_height, max_width, 3), dtype=int)
# stack images on canvas
start_height = 0
for img in imgs:
print(img.shape)
canvas[start_height:start_height+img.shape[0], 0:img.shape[1], :] = img
start_height+= img.shape[0]
# show results
plt.imshow(canvas)
This produces the following result:
When trying to join two images to create one:
img3 = imread('image_home.png')
img4 = imread('image_away.png')
result = np.hstack((img3,img4))
imwrite('Home_vs_Away.png', result)
This error sometimes appears:
all the input array dimensions for the concatenation axis must match exactly, but along dimension 0, the array at index 0 has size 192 and the array at index 1 has size 191
How should I proceed to generate the image when there is this difference in array size when np.hstack does not work?
Note:
I use several images, so not always the largest image is the first and not always the largest is the second, it can be quite random which is the smallest or largest between the two.
You can manually add a row/column with a color of your choice to match the shapes. Or you can simply let cv2.resize handle the resizing for you. In this code I show how to use both methods.
import numpy as np
import cv2
img1 = cv2.imread("image_home.png")
img2 = cv2.imread("image_away.png")
# Method 1 (add a column and a row to the smallest image)
padded_img = np.ones(img1.shape, dtype="uint8")
color = np.array(img2[-1, -1]) # take the border color
padded_img[:-1, :-1, :] = img2
padded_img[-1, :, :] = color
padded_img[:, -1, :] = color
# Method 2 (let OpenCV handle the resizing)
padded_img = cv2.resize(img2, img1.shape[:2][::-1])
result = np.hstack((img1, padded_img))
cv2.imwrite("Home_vs_Away.png", result)
Hi I am trying to compare a set of images where I want to produce a final image with maximum pixels from each individual image. Say I have 3 images (converted to 10x10 matrix) in which I know the pixel values of each block> Now I want to compare these values block by block and produce a final separate image with maximum block values from each image.
To do so I have changed the image dimensions(250x250) such that each block is a square of 25x25
I even tried comparing two images and taking the maximum pixels from both the images and displaying them
image = cv2.resize(im,(250,250))
hs,ws,c= image.shape
print(hs, ws,c)
hs = round(h/10)
ws = round(w/10)
resized = cv2.resize(image, (ws,hs), interpolation = cv2.INTER_AREA)
cv2.imshow("Resized image", resized)
cv2.waitKey(0)
cv2.destroyAllWindows()
print(list(resized))
#comparing two images
data = np.maximum.reduce([resized,resized1])
from matplotlib import pyplot as plt
plt.imshow(data, interpolation='nearest')
plt.show()
So these are two images and the tiled image is the result of the block #comparing two images. Now using these two images I want to produce a final image similar to the original photos not the tiled version but the final photo should have pixels from both original photos(maximum from each). I hope it clears the question
For better visualization purposes, I skip the whole resizing part you got earlier, and stick to resized (250 x 250) images.
My approach is the following: Store all your resized images in some NumPy array with dimensions (width x height x numberOfChannels x numberOfImages), and then use NumPy's max along axis=3, such that you get a final image (width x height x numberOfChannels) with maximum BGR values (or grayscale, if desired) over all images.
Here's some exemplary code:
import cv2
import numpy as np
# Set up empty images array
width, height, nChannels, nImages = (250, 250, 3, 3)
images = np.zeros((width, height, nChannels, nImages), np.uint8)
# Read and resize exemplary input images
images[:, :, :, 0] = cv2.resize(cv2.imread('WeQow.png'), (width, height))
images[:, :, :, 1] = cv2.resize(cv2.imread('gIHOd.png'), (width, height))
images[:, :, :, 2] = cv2.resize(cv2.imread('lAdfO.jpg'), (width, height))
# Generate maximum image along last axis, i.e. the images.
# For each BGR value you get the maximum over all images.
image = images.max(axis=3)
# Show images
cv2.imshow('image0', images[:, :, :, 0])
cv2.imshow('image1', images[:, :, :, 1])
cv2.imshow('image2', images[:, :, :, 2])
cv2.imshow('image', image)
cv2.waitKey(0)
cv2.destroyAllWindows()
These are the three input images:
The final output image then looks like this:
Hope that helps!
You can try using block_reduce function with block size (no_of_images, channels, block_height, block_width).
skimage.measure.block_reduce(np.asarray([image1, image2, image3,...]), (no_of_images, channels, 1, 1), np.max)
If your input images are in RGB scale and you want per-channel max value (output also RGB image) among images just replace channels value with 1 or if you want max value across channels among the images then use 3 as channels value that will generate a gray scale image.
I am loading an image with:
from keras.preprocessing import image
img = image.load_img(image_path, target_size=(224, 224))
x = image.img_to_array(img)
What I want to do is keep the dimension (224 x 224) but pad it. Where as normally, I'd have an image like this:
Instead, I want an image like:
(black border added for clarification. Not something I actually want)
What I want is for the image to be shifted (by some x and y) and for the rest to be zeroes.
The easiest approach is to create an empty matrix and fill the parts you want with the image:
x=np.ones((224,224,3),dtype=int)*255
x[x_start:,y_start:]=image.img_to_array[x_start:,y_start:]
Notice that you can change the dtype to uint8 if you need.
There is a function in numpy for padding matrices. You should specify padding value for each dimension.
np.pad(img, ((top_pad, bottom_pad), (left_pad, right_pad), (0, 0)), mode='constant', constant_values=0)
If you need an implementation take a look at this
I have a problem in size of image size (M*N)
when i read an image as np.array after i apply an algorithm method ,the size of its change to another value.some time increase and some times decrease depend on image.
img = cv2.imread('baboon.jpg',1) # read image (255*255)
na = np.array(img) # convert it to array
x, y ,pp = img.shape[:3] # size of 3d
blue = np.array(range(x*y), int).reshape((x, y))
blue[:,:] = na[:, :, 0]
en_split_block_8(red,31,1) # function algorithm
I use this code to save the image and the size changes from (255*255) to (640*480)
plt.imshow(blue,interpolation='nearest',cmap="gray")
plt.savefig('blue.jpg')#(640*480)
I want the image to keep it's size. (I don't change size of image just i work on values).
That's because you are saving the image with pyplot which shows the image as a diagram. What you want to do instead is save the blue image using cv2 with: cv2.imwrite('blue.jpg', blue).
Beware that na = np.array(img) is redundant as to why img is already an ndarray.