I am new to computational vision and python and I could not really figure out what went wrong. I have tried to randomize all the image pixels in a RGB image, but my image turned out to be completely wrong as seen below. Can someone please shed some light?
from scipy import misc
import numpy as np
import matplotlib.pyplot as plt
#Loads an arbitrary RGB image from the misc library
rgbImg = misc.face()
%matplotlib inline
#Display out the original RGB image
plt.figure(1,figsize = (6, 4))
plt.imshow(rgbImg)
plt.show()
#Initialise a new array of zeros with the same shape as the selected RGB image
rdmImg = np.zeros((rgbImg.shape[0], rgbImg.shape[1], rgbImg.shape[2]))
#Convert 2D matrix of RGB image to 1D matrix
oneDImg = np.ravel(rgbImg)
#Randomly shuffle all image pixels
np.random.shuffle(oneDImg)
#Place shuffled pixel values into the new array
i = 0
for r in range (len(rgbImg)):
for c in range(len(rgbImg[0])):
for z in range (0,3):
rdmImg[r][c][z] = oneDImg[i]
i = i + 1
print rdmImg
plt.imshow(rdmImg)
plt.show()
original image
image of my attempt in randomizing image pixel
You are not shuffling the pixels, you are shuffling everything when you use np.ravel() and np.shuffle() afterwards.
When you shuffle the pixels, you have to make sure that the color, the RGB tuples, stay the same.
from scipy import misc
import numpy as np
import matplotlib.pyplot as plt
#Loads an arbitrary RGB image from the misc library
rgbImg = misc.face()
#Display out the original RGB image
plt.figure(1,figsize = (6, 4))
plt.imshow(rgbImg)
plt.show()
# doc on shuffle: multi-dimensional arrays are only shuffled along the first axis
# so let's make the image an array of (N,3) instead of (m,n,3)
rndImg2 = np.reshape(rgbImg, (rgbImg.shape[0] * rgbImg.shape[1], rgbImg.shape[2]))
# this like could also be written using -1 in the shape tuple
# this will calculate one dimension automatically
# rndImg2 = np.reshape(rgbImg, (-1, rgbImg.shape[2]))
#now shuffle
np.random.shuffle(rndImg2)
#and reshape to original shape
rdmImg = np.reshape(rndImg2, rgbImg.shape)
plt.imshow(rdmImg)
plt.show()
This is the random racoon, notice the colors. There is not red or blue there. Just the original ones, white, grey, green, black.
There are some other issues with your code I removed:
Do not use the nested for loops, slow.
The preallocation with np.zeros is not needed (if you ever need it, just pass rgbImg.shape as argument, no need to unpack the separate values)
Change plt.imshow(rdmImg) into plt.imshow(rdmImg.astype(np.uint8))
This may related to this issue https://github.com/matplotlib/matplotlib/issues/9391/
Related
I am wondering is there any workaround to convert RGB images to pixel vectors without losing its spatial information in python. As far as I know, I can read the images and do transformation for images to pixel vectors. I am not sure doing this way still preserve images' spatial information in pixel vectors. How can I make this happen for making pixel vectors from RGB image?
my attempt:
I tried as follow but I am not sure how to make
import matplotlib.pyplot as pl
image = plt.imread('dog.jpg')
im = image/255.0
print(im.shape) #(32, 32, 3)
pixels = im.reshape(im.shape[0]*im.shape[1], im.shape[2])
but I want to make sure how to make pixel vectors from RGB images without losing pixel order and its spatial information. How to make this happen? any thoughts?
I think maybe numpy might have functions to do this. Can anyone point me how to do this with numpy?
graphic illustration:
here is simple graphic illustration of making pixel vectors from RGB images:
as this diagram shows, we have RGB images with shape of (4,4,3) which needs to make pixel vectors without losing its spatial information and pixel orders then combine pixel vectors from each channel (Red, Green, Blue) as pixel matrix or dataframe. I am curious how to get this done in python?
goal:
I want to make pixel vectors from RGB images so resulted pixel vectors needs to be expanded with taylor expansion. Can anyone point me out how to make this happen?
Are You just trying to reshape each channel to a vector and then joining them horizontally? That's what I understood from the graphic illustration and the way i would do it is something like this:
import matplotlib.pyplot as plt
import numpy as np
image = plt.imread('monkey.png')
image = image / 255.0
red = image[:,:,0]
green = image[:,:,1]
blue = image[:,:,2]
def to_vector(matrix):
result = []
for i in range(matrix.shape[1]):
result = np.vstack(matrix[:,i])
return result
red = to_vector(red)
green = to_vector(green)
blue = to_vector(blue)
vector = np.hstack((red,green,blue))
Your original attempt was almost a full solution - maybe actually a full solution, depending on what the idea is.
print(im.shape) #(32, 32, 3)
pixels = im.reshape(im.shape[0]*im.shape[1], im.shape[2]) # this is exactly correct
print(pixels.shape) #(1024,3)
reds = pixels[:, 0] #just as an example for where things end up in the result
pixels_channelfirst = np.moveaxis(pixels, 1, 0) # if you want the first axis to be channels
print(pixels.shape) #(3, 1024)
reds = pixels[0, :]
"I want to preserve its pixel order and spatial information" - this does that already! Add one non-zero pixel to a zero image and plot where it goes, if you have doubts. np.hstack in the other answer does as well.
I have a greyscale image, represented by a 2D array of integers, shape (1000, 1000).
I then use sklearn.feature_extraction.image.extract_patches_2d() to generate an array of 3x3 'patches' from this image, resulting in an array of shape (1000000, 3, 3), as there are 1 million 3x3 arrays for each pixel value in the original image.
I reshape this to (1000, 1000, 3, 3), which is a 1000x1000 array of 3x3 arrays, one 3x3 array for each pixel in the original image.
I now want to effectively subtract the 2D array from the 4D array. I have already found a method to do this, but I would like to make one using vectorisation.
I currently iterate through each pixel and subtract the value there from the 3x3 array at the same index. This is a little bit slow.
This is what currently loads images, formats the arrays before hand, and then performs this subtraction.
from PIL import Image, ImageOps
from skimage import io
from sklearn.feature_extraction import image
import numpy
jitter = 1
patchsize = (jitter*2)+1
#load image as greyscale image using PIL
original = load_image_greyscale(filename)
#create a padded version of the image so that 1000x1000 patches are made
#instead of 998x998
padded = numpy.asarray(ImageOps.expand(original,jitter))
#extract these 3x3 patches using sklearn
patches = image.extract_patches_2d(padded,(patchsize,patchsize))
#convert image to numpy array
pixel_array = numpy.asarray(original)
#then reshape the array of patches so it matches array_image
patch_array = numpy.reshape(patches, (pixel_array.shape[0],pixel_array.shape[1],patchsize,patchsize))
#create a copy for results
patch_array_copy = numpy.copy(patch_array)
#iterate over each 3x3 array in the patch array and subtract the pixel value
#at the same index in the pixel array
for x in range(pixel_array.shape[0]):
for y in range(pixel_array.shape[1]):
patch_array_copy[x,y] = patch_array[x,y] - pixel_array[x,y]
I would like a way to perform the final step in the for loop using matrix operations.
I would also like to extend this at some point to work with RGB images, effectively making it a subtraction of an array with shape(1000,1000,3) from an array with shape(1000,1000,3,3,3). But i'm trying to go one step at a time here.
Any help or tips or suggestions or links to helpful resources would be greatly appreciated.
My goal is to display a 2D Array as a image in Python. The array doesn't contain zero elements, and therefore I would expect an image in which imshow() automatically sets the color scale according to the array values. However, when I run the code, the image is blank.
The csv file is: https://ufile.io/urk5m
import numpy as np
import matplotlib.pyplot as plt
data_ = np.loadtxt(open("new_file.csv", "rb"), delimiter=",")
plt.imshow(data_)
My result is this: https://imgur.com/jMNnF0h
Always remember, but really always, that images works on 8bit integers. Thats why there is 2^8 shades of gray and why most commmon number of CS colors is (2^8)^3= 16.7 mil. colors. 3 because there are 3 color channels - RGB, each having 256 shades.
Everybody is counting with it and mainly the image processing libraries.
Therefore ALWAYS make sure you pass correct matrix datatype into image processing functions:
image_8bit = np.uint8(data_)
plt.imshow(image_8bit)
plt.show()
I'm new to Python and i need to draw a RGB spectrum as a numpy array.
For me it's clear that i need to rise the RGB values across the dimensions to get the spectrum.
import numpy as np
import matplotlib.pyplot as plt
spectrum = np.zeros([255,255, 3], dtype=np.unit8) #init the array
#fill the array with rgb values to create the spectrum without the use of loops
plt.imshow(spectrum)
plt.axis('off') # don't show axis
plt.show()
Is there a possiblity (e.g. a python or numpy method) to create the spectrum without the use of loops?
Not sure if this is the result you'd like, but you could define the arrays for the RGB values yourself (see HSV-RGB comparison). I've used Pillow to convert grayscale to colour.
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
spectrum = np.zeros([256,256*6, 3], dtype=np.uint8) # init the array
# fill the array with rgb values to create the spectrum without the use of loops
spectrum[:,:,0] = np.concatenate(([255]*256, np.linspace(255,0,256), [0]*256, [0]*256, np.linspace(0,255,256), [255]*256), axis=0)
spectrum[:,:,1] = np.concatenate((np.linspace(0,255,256), [255]*256, [255]*256, np.linspace(255,0,256), [0]*256,[0]*256), axis=0)
spectrum[:,:,2] = np.concatenate(([0]*256, [0]*256,np.linspace(0,255,256),[255]*256, [255]*256, np.linspace(255,0,256)), axis=0)
img = Image.fromarray(spectrum, 'RGB')
img.show()
Below is a simple section of code used to access an image using PIL, convert to a numpy array and then print the number of elements in the array.
The image in question is here - - and consists of exactly 100 pixels (10x10). However, the numpy array contains 300 elements (where I would expect 100 elements). What am I doing wrong?
import numpy as np
import PIL
impath = 'C:/Users/Ricky/Desktop/testim.tif'
im = PIL.Image.open(impath)
arr = np.array(im)
print arr.size #300
Every image can be composed by 3 bands (Red-Green-Blue or RGB composition).
Since your image is a black/white image those three bands are the same. You can see the difference using a colored image.
Try this to see what I mean:
import matplotlib.pyplot as pyplot
# this line above import a matplotlib library for plotting image
import numpy as np
import PIL
impath = 'C:/Users/Ricky/Desktop/testim.tif'
im = PIL.Image.open(impath)
arr = np.array(im)
print arr.shape # (10, 10, 3)
print arr[:, : ,0].size # 100
# next lines actually show the image
pyplot.imshow(arr[:, : ,0], cmap='gray')
pyplot.show()