I have an image stack of 500 images (jpeg) of 640x480. I intend to make 500 pixels (1st pixels of all images) as a list and then send that via COM1 to FPGA where I do my further processing.
I have a couple of questions here:
How do I import all the 500 images at a time into python and how do i store it?
How do I send the 500 pixel list via COM1 to FPGA?
I tried the following:
Converted the jpeg image to intensity values (each pixel is denoted by a number between 0 and 255) in MATLAB, saved the intensity values in a text file, read that file using readlines(). But it became too cumbersome to make the intensity value files for all the 500 images!
Used NumPy to put the read files in a matrix and then pick the first pixel of all images. But when I send it, its coming like: [56, 61, 78, ... ,71, 91].
Is there a way to eliminate the [ ] and , while sending the data serially?
Thanks in Advance! :)
Ad 1: Use a library like PIL for accessing the images. You can load an image using
from PIL import Image
im = Image.open("img000.jpg")
And access the first pixel value using
pixel = im.getpixel(0,0)
This returns a color tuple for the first pixel, you have to calculate the intensity from this.
Ad 2: This depends on how your FPGS expects the values? Since you mentioned eliminating [ , do you need a comma-separated ASCII string? Try
pixel_string = ','.join([str(x) for x in pixel_list])
If you need to send a series of bytes construct the byte string like
pixel_string = ''.join([chr(x) for x in pixel_list])
Both examples assume, that you have constructed you list of intensity values in pixel_list.
Related
Question
With an image loaded into Python as shown below, how do I know which order the channels are in? (e.g. BGR or RGB)
Code
from PIL import Image
import numpy as np
image_pil = Image.open("Stonehenge.jpg")
image_np = np.array(image_pil)
image_np[0][0]
Result
array([ 52, 123, 155], dtype=uint8)
Specific question
How do I know whether the 52 corresponds to the red channel, the blue channel, or a different channel? Or does this question not make sense on a conceptual level?
Notes
In a similar question for Java instead of Python, one person claims:
If you are reading in the image file, or you have access to the code
that reads in the file, know it is:
BGR order if you used cv2.imread(),
RGB order if you used mpimg.imread(), (assuming import matplotlib.image as mpimg)
If you don't know how the file was opened, the accepted answer
BufferedImage is great for Java.
Since you use PIL and you don't specify any other mode to load the Image with, you get R G B.
You could verify that by checking the "mode" attribute on the Image instance:
image_pil.mode # should return the string 'RGB'
Pillow supports the array interface, via image_pil.__array_interface__ magic method, so when when you create the ndarray numpy just uses that. i.e., it doesn't know anything about the colour channel order. If you have an image file stored as BGR, and you load it like this, you will get blue data in the red channel and vice-versa, and it would look wrong when you display it.
I have tens of thousands of text files to analyze, where each text file represents a snapshot in time of the physical state of a system. The micro-state of each "pixel" is represented by floats from 0 to 1. Is it possible for OpenCV to directly read a text file without first having to convert the text file to an image format? I do not want to create tens of thousands of image files every time I carry out this analysis.
Context/goal: I am analyzing a thermal simulation of a nano-magnetic system, and will eventually need to use OpenCV to calculate the contour areas of clusters formed above a certain threshold value.
I've included my code attempt below, using a test text file. The system is a square system of side length 40, and I am analyzing the column of 40^2 = 1600 data points which I call mag (for magnetization, as this is from a scientific research project). I multiply each "pixel" by 255 to mimic grayscale. As soon as the program reaches the cv2.threshold line, I get an error:
~/anaconda/conda-bld/work/opencv-2.4.8/modules/imgproc/src/thresh.cpp:783: error: (-210) in function threshold
which I suspect arises from my mimicking grayscale instead of reading an actual grayscale image file.
import numpy as np
import cv2
SideDim = 40
dud, mag = np.loadtxt('Aex_testfile.txt', unpack=True, usecols=(4,5), skiprows=2)
mag = np.reshape(mag, (SideDim,SideDim))
for row in range(SideDim):
for col in range(SideDim):
mag[row][col] = round(255 * mag[row][col])
mag = mag.astype(np.int)
ret,thresh = cv2.threshold(mag,0,255,cv2.THRESH_BINARY)
plt.imshow(thresh,'gray')
Regarding the question in your post title:
In Python, CV2 does not convert text into an image format. Instead, "images" are just numpy arrays. You are then correct in using np.loadtxt to import data (though I'm partial to np.genfromtxt(), as it's slightly more robust).
Regarding the error you're getting:
Error code -210 is defined as:
#define CV_StsUnsupportedFormat -210 /* the data format/type is not supported by the function*/
cv2.threshold() uses an 8 bit integer. Instead of casting mag as np.int, cast it as np.uint8. This should fix your error
Other things to note:
With numpy arrays, you don't need to use those ugly nested loops to multiply each value by 255. Instead, just do mag * 255.
Instead of multiplying by 255 (which doesn't quite make sense unless you're positive your maximum value is 1...), you should really just normalize your array. Something like (mag / mag.amax()) * 255 would be a better solution.
You don't need open CV for this part of the program. Instead, you can just do it in numpy:
thresh = 255 * (mag > threshval)
this will produce an array (thresh) that has any values greater than threshval set equal to 255
In general, I think it would behoove you to learn numpy before jumping into opencv. I think you'd be surprised at how much you can do in numpy.
I'm attempting to make a reasonably simple code that will be able to read the size of an image and return all the RGB values. I'm using PIL on Python 2.7, and my code goes like this:
import os, sys
from PIL import Image
img = Image.open('C:/image.png')
pixels = img.load()
print(pixels[0, 1])
now this code was actually gotten off of this site as a way to read a gif file. I'm trying to get the code to print out an RGB tuple (in this case (55, 55, 55)) but all it gives me is a small sequence of unrelated numbers, usually containing 34.
I have tried many other examples of code, whether from here or not, but it doesn't seem to work. Is it something wrong with the .png format? Do I need to further code in the rgb part? I'm happy for any help.
My guess is that your image file is using pre-multiplied alpha values. The 8 values you see are pretty close to 55*34/255 (where 34 is the alpha channel value).
PIL uses the mode "RGBa" (with a little a) to indicate when it's using premultiplied alpha. You may be able to tell PIL to covert the to normal "RGBA", where the pixels will have roughly the values you expect:
img = Image.open('C:/image.png').convert("RGBA")
Note that if your image isn't supposed to be partly transparent at all, you may have larger issues going on. We can't help you with that without knowing more about your image.
I am looking to store pixel values from satellite imagery into an array. I've been using
np.empty((image_width, image_length)
and it worked for smaller subsets of an image, but when using it on the entire image (3858 x 3743) the code terminates very quickly and all I get is an array of zeros.
I load the image values into the array using a loop and opening the image with gdal
img = gdal.Open(os.path.join(fn + "\{0}".format(fname))).ReadAsArray()
but when I include print img_array I end up with just zeros.
I have tried almost every single dtype that I could find in the numpy documentation but keep getting the same result.
Is numpy unable to load this many values or is there a way to optimize the array?
I am working with 8-bit tiff images that contain NDVI (decimal) values.
Thanks
Not certain what type of images you are trying to read, but in the case of radarsat-2 images you can the following:
dataset = gdal.Open("RADARSAT_2_CALIB:SIGMA0:" + inpath + "product.xml")
S_HH = dataset.GetRasterBand(1).ReadAsArray()
S_VV = dataset.GetRasterBand(2).ReadAsArray()
# gets the intensity (Intensity = re**2+imag**2), and amplitude = sqrt(Intensity)
self.image_HH_I = numpy.real(S_HH)**2+numpy.imag(S_HH)**2
self.image_VV_I = numpy.real(S_VV)**2+numpy.imag(S_VV)**2
But that is specifically for that type of images (in this case each image contains several bands, so i need to read in each band separately with GetRasterBand(i), and than do ReadAsArray() If there is a specific GDAL driver for the type of images you want to read in, life gets very easy
If you give some more info on the type of images you want to read in, i can maybe help more specifically
Edit: did you try something like this ? (not sure if that will work on tiff, or how many bits the header is, hence the something:)
A=open(filename,"r")
B=numpy.fromfile(A,dtype='uint8')[something:].reshape(3858,3743)
C=B*1.0
A.close()
Edit: The problem is solved when using 64bit python instead of 32bit, due to memory errors at 2Gb when using the 32bit python version.
I am using Python and the PIL library and I have the RGB information for every pixel of an image along with their location. Is there any way that I can build an image from this information?
Certainly. If your source data is sparse (ie. you don't have a value for every pixel location) you probably want to do the following:
create an empty image of the required dimensions
ensure your colour data is stored in raster order (ie. sort by y then x)
iterate through the data and store the pixel values in each location
So, assuming you have an array of tuples such as (x, y, (r,g,b)), you can do something like:
from pil import Image
WIDTH=640
HEIGHT=480
img = Image.new(WIDTH, HEIGHT, 'RGB')
# Define this based on your data
my_raster_sort(my_image_data)
img_data = img.load()
for x, y, color in my_image_data:
img_data[x,y] = color
If your source image data is complete (ie. you have a colour value for every position) then it would probably be faster to transform your data into a buffer formatted with the desired memory layout, and then create an image in one step using Image.frombuffer.
Yes. That's what Image.putpixel() (and possibly putdata() depending on how you have the data) are for. Find the documentation for these methods here.
Hard to advise you further since you provided no code or even a sample of the data.