I have 4 different objects with a numpy array (image), how could I merge them into another numpy 3d array (2d and 3 elements in every position) so that I have just one image containing those 4 different image.
For example, lets say I have Img1, Img2, Img3 and Img4, which are independent images and are currently stored in a 2D array like this:
Img1, Img2
Img3, Img4
So what I want is to access to the 2D array where these Img are and then create one single image with them in that order. I have this which works for this example so you can figure out what I need, but I need something generic and efficient, for example to have it a while instead of in 2 nested for:
a = np.hstack((images[0][0], images[0][1]))
b = np.hstack((images[1][0], images[1][1]))
c = np.vstack((a,b))
misc.imshow(c)
This code creates one single image from those I mentioned but I need it to be able to handle any subimage to create the main image, plus need it to be efficient (like having just a while instead of 2 for) :/
Can someone give me a hand please?
Thanks and regards.
Related
I am writing some codes to cut two seprate ROI regions in an numpy array. The array is a mask array with boolean values and it consists of two major left and right parts.
I need to crops those left and right parts from my original numpy array. My codes are as follow which are a section of function (image and masked are passed to this function)
if mask.shape[-1] > 0:
# We're treating all instances as one, so collapse the mask into one layer
mask = (np.sum(mask, -1, keepdims=True) >= 1)
zeros=np.zeros(image.shape)
#splash = np.where(mask, image, gray).astype(np.uint8)
splash = np.where(mask, image, zeros).astype(np.uint8)
I am not sure how to achieve this as I am really new to bumpy. I can splash the imge but what I need is differt I ned to crop two left and right parts and for this I need to crop or reshape the mask array. I have attached a splashed output sample to this thread
This is a very typical problem in computer vision. One popular solution to this is the Connected Component Labeling (or CCL). OpenCV has already an implementation for this:
https://docs.opencv.org/3.4/d3/dc0/group__imgproc__shape.html#gaedef8c7340499ca391d459122e51bef5
Then you may use blob analysis to crop out the objects:
https://docs.opencv.org/3.4/d0/d7a/classcv_1_1SimpleBlobDetector.html
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.
Using OpenCV and Python, I want to display the left hand half of one image concatenated with the right-hand half of another image, both of the same size - 512x512 pixels. I have identified several ways of doing this, but I am confused about the behaviour of one method. In the following code, assume that only one of the methods is used at any one time and the rest are commented out:
import cv2
import numpy as np
image1 = cv2.imread('img1.png',0)
image2 = cv2.imread('img2.png',0)
#Method 1 - works
image3 = np.concatenate([image1[:,0:256], image2[:,256:512]], axis=1)
#Method 2 - works
image3 = image1[:,:]
image3[:,256:512] = image2[:,256:512]
#Method 3 - works if I don't create image3 with np.zeros first.
#Otherwise displays black image - all zeros - but print displays correct values
image3 = np.zeros(shape=(512,512), dtype=int)
image3[:,0:256] = image1[:,0:256]
image3[:,256:512] = image2[:,256:512]
print(image3)
cv2.imshow("IMAGE", image3)
cv2.waitKey(0)
cv2.destroyAllWindows()
In method 3, I at first mistakenly thought that the new numpy array image 3 would need to be created first and so created an array filled with zeros and then seemingly overwrote that array with the correct values. When I print that array it displays the correct values, but when I show it as an image using cv2.imshow it is all black (i.e. all zeros). Why the difference? I understand that slicing creates a view, not a copy, but can someone please explain what is happening in method 3 and why cv2.imshow displays the underlying array but print doesn't.
Your problem is in:
np.zeros(shape=(512,512), dtype=int)
imshow will show images coded as float(32 bit) with a range of 0.-1. or 8bit(1-4 channels) with a range of 0-255. You are using int, which is 32 bit (in most cases) and it is not a floating point. What you should do to fix it, is to use np.uint8.
np.zeros(shape=(512,512), dtype=np.uint8)
I think also it can be displayed using matplotlib if you want to keep the int, but I am not 100% sure about it.
I have several images which I want to aggregate in a new image 8 image per column, 5 per row side by side with openCV in Python.
Curiously, I did not find an answer which directly addresses this question. From my spare knowledge on openCV, I would now count the width and height of the image to which the existing images should be copied, create a numpy Array with these images and change the values of the corresponding regions of Pinterest to values of each image.
Would this procedure work and more important isn't there an easier solution for this problem which haven't found?
When images are read in OpenCV's Python API, you get Numpy arrays. Numpy has vstack() and hstack() functions, which you can use to stack arrays (images) vertically and horizontally.
Let's open up two images with OpenCV:
import cv2
import numpy as np
knight = cv2.imread('knight.jpg', cv2.IMREAD_GRAYSCALE)
To use stacking in numpy, there are restriction on the image dimensions depending on the stackng axis (vertical/horizontal), so for this image, I will use cv2.resize() to get the right dimensions
queen = cv2.imread('queen.jpg', cv2.IMREAD_GRAYSCALE)
queen = cv2.resize(queen, (525, 700))
Let's make a first column by stacking 2 Knights
col_1 = np.vstack([knight, knight]) # Simply put the images in the list
# I've put 2 knights as example
Now let's make a second column with 2 Queens
col_2 = np.vstack([queen, queen])
Let's put those two columns together, but this time we'll use hstack() for that
collage = np.hstack([col_1, col_2]
Et voila, a collage of 2 x 2 which you can adapt to your needs. Note that the images passed in the stacking do need to be identical or anything, you can pass in any list of images, as long as you respect the dimensions.
In case anyone else finds it useful, here is a quick example of generalizing #bakkal's code to creating a collage out of an arbitrary number of images. It creates a collage (for simplicity, a kxk square collage, and all images are assumed to be of the same size - o.w, don't forget to resize your images!) from a directory of images, by first horizontally stacking images to create k rows, and then vertically stacking the rows to create the final canvas.
import os
def create_collages(image_dir):
image_paths = os.listdir
n = len(image_paths)
# find nearest square
collage_size = int(math.floor(math.sqrt(len(good_paths))))
# horizontally stacking images to create rows
rows = []
k = 0 # counter for number of rows
for i in range(collage_size**2):
if i % collage_size == 0: # finished with row, start new one
if k > 0:
rows.append(cur_row)
cur_row = cv2.imread(os.path.join(image_dir, image_paths[i]))
k += 1
else: # continue stacking images to current row
cur_img = cv2.imread(os.path.join(image_dir, image_paths[i]))
cur_row = np.hstack([cur_row, cur_img])
# vertically stacking rows to create final collage.
collage = rows[0]
for i in range(1, len(rows)):
collage = np.vstack([collage, rows[i]])
return collage
Resize all the images and are placed in a folder(input_dir). Here is simple a solution, collage_size parameter says how many images in the collage (r-row, c-col). It will take a random sample of r*c images if there are more images in the folder so that it can give a overall representation. I have been personally using this analyzing variety of objects from training an object detection model.
def create_collage(input_dir, collage_size):
r, c = collage_size
images_outers= []
for i in range(r):
images = []
for image_name in sample(os.listdir(input_dir), c):
print(image_name)
image = cv2.imread(os.path.join(input_dir, image_name))
images.append(image)
image_outer = np.hstack(images)
images_outers.append(image_outer)
return(np.vstack(images_outers))
Ok, so here is my code. om is the array I'm comparing im to. I'm hoping the array is in the format [b, g, r]
import cv2
import numpy as np
import time
om=cv2.imread('RGB.png')
om=om.reshape(1,-1,3)
while True:
cam = cv2.VideoCapture(0)
start=time.time()
while(cam.isOpened()):
ret, im = cam.read()
im=cv2.resize(im,(325,240))
im= im.reshape(1,-1,3)
Ok, so I'm hoping the arrays are based off of all the pixel colours in them and that they are 1D (reshape should have done that?). Duplicates aren't necessary but like, if possible I would like to keep them.
I want to intersect om with im and get the value of the number of elements intersecting. I tried the in1d thing, but it would return Trues and Falses. I'm half wondering if it would be easier to count them?/ the trues.
Also, if I do use the in1d function, does that only count corresponding pixels? (like, that the pixel height and row matter) or is it only pixel bgr? because I am only after bgr.
Basically, I wanna see how many pixels have the same colour value as those in the picture I already have saved.
Btw, I tried using sets, but they were fairly slow and difficult to get into the correct order (I seemed to be getting only one element a set).
intersection = [x for x in list_1 if x in list_2]