EDIT: I have found a workaround, which is assigning it to an array, then use that array to create a numpy array:
a = []
for i in range(0,width/image_size):
for j in range(0,height/image_size):
roi = img[image_size*j:image_size*(j+1),image_size*i:image_size*(i+1)]
a.append(roi)
arr = np.asarray(a) #HERE
ORIGINAL QUESTION:
I have created an empty numpy array of shape (180,28,28), which should hold 180 gray scale images size 28x28.
height, width = img.shape[:2]
arr = np.empty(((height/image_size)*(width/image_size), 28, 28 )) #arr.shape = (180,28,28)
I have multiple image regions size 28x28 that I want to populate into arr
for i in range(0,width/image_size):
for j in range(0,height/image_size):
roi = img[image_size*j:image_size*(j+1),image_size*i:image_size*(i+1)]
#HERE - how can I set the value in arr to be an (28x28) roi
Thank you.
I have found a workaround, which is assigning it to an array, then use that array to create a numpy array:
a = []
for i in range(0,width/image_size):
for j in range(0,height/image_size):
roi = img[image_size*j:image_size*(j+1),image_size*i:image_size*(i+1)]
a.append(roi)
arr = np.asarray(a) #assign it to numpy array here
However, I'm not sure if there is a better, or more elegant way to do it.
Related
I want to do some operation in numpy array. Actually I'm trying to zoom an image using the nearest neighbour rule. I have facing that above titled issue.
import cv2
import numpy as np
from numpy import ndarray
img = cv2.imread('abc.jpg')
rows = img.shape[0]*2
cols = img.shape[1]*2
zoomed = np.zeros((rows, cols), dtype=img.dtype)
for i in range(0, rows):
for j in range(0, cols):
zoomed[i][j] = img[int(i/2)][int(j/2)]
cv2.imshow('Input Image', img)
cv2.imshow('Zoomed Image', zoomed)
cv2.waitKey(0)
Try:
zoomed = np.zeros((rows, cols, 3), dtype=img.dtype)
The error you're getting is happening because img[int(i/2)][int(j/2)] is actually three RGB values and zoomed[i][j] can only hold integers. Creating zoomed to have shape (rows, cols, 3) allows zoomed to hold 3 integers at every row, column location.
I'm trying to calculate image histograms of an numpy array of images. The array of images is of shape (n_images, width, height, colour_channels) and I want to return an array of shape (n_images, count_in_each_bin (i.e. 255)). This is done via two intermediary steps of averaging each colour channel for each image and then flattening each 2D image to a 1D one.
I think have successfully done this with the code below, however I have cheated a bit with the for loop at the end. My question is this - is there a way of getting rid of the last for loop and using an optimised numpy function instead?
def histogram_helper(flattened_image: np.array) -> np.array:
counts, _ = np.histogram(flattened_image, bins=[n for n in range(0, 256)])
return counts
# Using 10 RGB images of width and height 300
images = np.zeros((10, 300, 300, 3))
# Take the mean of the three colour channels
channel_avg = np.mean(images, axis=3)
# Flatten each image in the array of images, resulting in a 1D representation of each image.
flat_images = channel_avg.reshape(*channel_avg.shape[:-2], -1)
# Now calculate the counts in each of the colour bins for each image in the array.
# This will provide us with a count of how many times each colour appears in an image.
result = np.empty((0, len(self.histogram_bins) - 1), dtype=np.int32)
for image in flat_images:
colour_counts = self.histogram_helper(image)
colour_counts = colour_counts.reshape(1, -1)
result = np.concatenate([result, colour_counts])
You don't necessarily need to call np.histogram or np.bincount for this, since pixel values are in the range 0 to N. That means that you can treat them as indices and simply use a counter.
Here's how I would transform the initial images, which I imaging are of dtype np.uint8:
images = np.random.randint(0, 255, size=(10, 5, 5, 3)) # 10 5x5 images, 3 channels
reshaped = np.round(images.reshape(images.shape[0], -1, images.shape[-1]).mean(-1)).astype(images.dtype)
Now you can simply count the histograms using unbuffered addition with np.add.at:
result = np.zeros((images.shape[0], 256), int)
index = np.arange(len(images))[:, None]
np.add.at(result, (index, reshaped), 1)
The last operation is in-place and therefore returns None, but the answer will be in result nevertheless.
arr = []
for i in range(len(x1)):
image = x1[i].reshape(150, 150, 3)
grayscale = image[0:150, 0:150, 1]
grayscale = grayscale.reshape(22500)
arr = np.append(arr, np.array(grayscale), axis=0)
print(arr.shape) # (742500,)
I am working on a school project, and I have created more data with augmentation in RGB format. I would like to convert this to grayscale after augmentation because it will require fewer computations. However, for some reason, I am having problems with appending the reshaped version into a new array. It is append everything into one row and not to a separate rows, I want to have (33,22500) not (742500), can anyone help plz
there are several ways;
way1:
arr = []
for i in range(len(x1)):
image = x1[i].reshape(150,150,3)
grayscale = image[:150,:150,1]
grayscale = grayscale.reshape(22500)
arr.append(grayscale)
arr = np.array(arr)
I'm trying to mask a 3D array (RGB image) with numpy.
However, my current approach is reshaping the masked array (output below).
I have tried to follow the approach described on the SciKit-Image crash course.
Crash Course
I have looked in the Stackoverflow and a similar question has been asked, but with no accepted answer (similar question here)
What is the best way to accomplish masking like this?
Here is my attempt:
# create some random numbers to fill array
tmp = np.random.random((10, 10))
# create a 3D array to be masked
a = np.dstack((tmp, tmp, tmp))
# create a boolean mask of zeros
mask = np.zeros_like(a, bool)
# set a few values in the mask to true
mask[1:5,0,0] = 1
mask[1:5,0,1] = 1
# Try to mask the original array
masked_array = a[:,:,:][mask == 1]
# Check that masked array is still 3D for plotting with imshow
print(a.shape)
(10, 10, 3)
print(mask.shape)
(10, 10, 3)
print(masked_array.shape)
(8,)
# plot original array and masked array, for comparison
plt.imshow(a)
plt.imshow(masked_array)
plt.show()
NumPy broadcasting allows you to use a mask with a different shape than the image. E.g.,
import numpy as np
import matplotlib.pyplot as plt
# Construct a random 50x50 RGB image
image = np.random.random((50, 50, 3))
# Construct mask according to some condition;
# in this case, select all pixels with a red value > 0.3
mask = image[..., 0] > 0.3
# Set all masked pixels to zero
masked = image.copy()
masked[mask] = 0
# Display original and masked images side-by-side
f, (ax0, ax1) = plt.subplots(1, 2)
ax0.imshow(image)
ax1.imshow(masked)
plt.show()
After finding the following post on loss of dimensions HERE, I have found a solution using numpy.where:
masked_array = np.where(mask==1, a , 0)
This appears to work well.
How to import RGB value of each pixel in an image to 1-D array?
I am using following thing:
from PIL import Image
im = Image.open("bride.jpg")
pix = im.load()
print pix[x,y]
this imports it into 2-D array which is not iterable.
I want this same thing but in 1-D array.
You can flatten the pixels into a 1D array as follows:
width, height = im.size
pixels = [pix[i, j] for i in range(width) for j in range(height)]
Easy if you're using numpy, and no need to load the image.
from PIL import Image
import numpy as np
im = Image.open("bride.jpg")
pix_flatiter = np.asarray(im).flat # is an iterable
If you want to load the whole array, you can do:
pix_flat = np.asarray(im).flatten() # is an array