rmagick color out of range - ruby

I am trying to average the colours in an image, I have come up with the following script (from here):
scrip.rb:
require 'rmagick'
file = "./img.jpg"
img = Magick::Image.read(file).first
color = img.scale(1, 1).pixel_color(0,0)
p [color.red, color.green, color.blue]
img.jpg:
BUT the RGB output is [31829, 30571, 27931].
Questions:
Shouldn't the numbers be in the range of [0-255]?
What am I doing wrong?

What you have there is the red, green, and blue histogram values.
You need to divide by 256 in order to get each RGB value. In this case, the RGB values are:
require 'rmagick'
file = "./img.jpg"
img = Magick::Image.read(file).first
color = img.scale(1, 1).pixel_color(0,0)
p [color.red/256, color.green/256, color.blue/256]
# => [124, 119, 109]
This blog post provides a more thorough explanation on how to analyse images with RMagick.

The reason for the odd output is due to the bit depth. As a previous answer states, "They are stored in a 'quantum depth' of 16-bits." This was an initial assumption, but by looking at previous answers, this makes more sense. In order to properly convert these numbers back to your typically desires [0-255] range, you must divide the values by 256.
Note: You can change the quantum depth during runtime. When reading the file, you should be able to use a block like shown in the following code.
img = Magick::Image.read(file){self.depth = 8}.first

Related

How to convert a label without color palette to a class array

I tried to convert a label (rgb, with shape [x,y,3]) image to a single channel class
Image ([x,y]), where every colors is one class from 0 to the number of classes in the
Image. The Problem here: I cannot use a color palette and the colors are completly
unknown
just as the total number of classes. So here is how I tried to solve this problem:
img = cv2.imread(path+".png")
pic_in = np.array(img)
#Get Class Number
label_class = np.zeros((size, size), dtype=np.uint8)
numbers = []
for x in range(PredictionClass.shape[0]):
for y in range(PredictionClass.shape[1]):
tempint=pic_in[x][y][0]*256*256+pic_in[x][y][1]*256+pic_in[x][y][2]
if tempint not in numbers:
numbers.append(tempint)
label_class[x][y]=int(numbers.index(tempint))
But as you can see, I am iterating over pixels, which is normally not the best idea... As I am still learning, I wondered if someone knows a better solution for such a problem - I just saw solutions for "static problems, with color pallets and fixed known class number".
Thank you very much :)

How can I find the size of an image?

I need the size of the image as a variable.
Here is what I tried:
a = dir('C:\example\Desktop\imagefolder\*.png');
numberofImages = length(a);
%sizeofimage?
matrix = zeros(numberofImages, sizeofimage);
How can I get the size of my image?
Maybe this will help. It will give you the size of each of the images in your folder.
a = dir('C:\example\Desktop\imagefolder\*.png');
numberofImages = length(a);
for i=1:numberofImages
img = imread(a(i).name);
sizeofImage{i} = size(img)
end
You can then access the sizes of the images using this notation:
sizeofImage{1}
Which will return something like this for an image 400x400:
ans =
400 400 3
You require an array of numbers to go into zeros, and size already provides you with one. Simply horzcat that (or use square brackets) with the number of images and you're done:
matrix = zeros([numberofImages, size(image)]);
Although I strongly suggest you to stop working on your project and start taking a class in MATLAB, read a book on it or take the MathWorks own tutorial, as this is about as basic as MATLAB gets. Since MATrix LABoratory is about matrices, size is important.

PIL: Imageobject.save() after drawing completely corrupts images and smurfs the ouput

I have these two functions in my program:
def depict_ph_increase(x,y,color, imobject):
program_print(color)
draw = PIL.ImageDraw.Draw(imobject)
draw.text((x, y),color,(255,255,255))
imobject.save('tmp-out.gif')
im_temp = PIL.Image.open("tmp-out.gif")#.convert2byte()
im_temp = im_temp.resize((930, 340), PIL.Image.ANTIALIAS)
MAP_temp = ImageTk.PhotoImage(im_temp)
map_display_temp = Label(main, image=MAP_temp)
map_display_temp.image = MAP_temp # keep a reference!
map_display_temp.grid(row=4,column=2, columnspan=3)
def read_temp_pixels(temperature_file, rngup, rngdown):
temp_image_object = PIL.Image.open(temperature_file)
(length, width) = get_image_size(temp_image_object)
(rngxleft, rngxright) = rngup
(rngyup,rngydown) = rngdown
print 'the length and width is'
print length, width
hotspots = 5;
for hotspot in range(0,hotspots):
color = "#ffffff"
while color == "#ffffff" or color == "#000000" or color == "#505050" or color == "#969696":
yc = random.randint(rngxleft, rngxright)
xc = random.randint(rngyup,rngydown)
color = convert_RGB_HEX(get_pixel_color(temp_image_object, xc, yc))
depict_ph_increase(xc,yc,color, temp_image_object)
The bottom one calls the top one. Their job is to read in this image:
It then randomly selects a few pixels, grabs their colors, and writes the hex values of the colors on top. But, when it redisplays the image, it gives me this garbage:
Those white numbers up near the upper right corner are the hex values its drawing. Its somehow reading the values from the corrupted image, despite the fact that I don't collect the values until AFTER I actually call the ImageDraw() method. Can someone explain to me why it is corrupting the image?
Some background--the get_pixel_color() function is used several other times in the program and is highly accurate, its just reading the pixel data from the newly corrupted image somehow. Furthermore, I do similar image reading (but not writing) at other points in my code.
If there is anything I can clarify, or any other part of my code you want to see, please let me know. You can also view the program in its entirety at my github here: https://github.com/jrfarah/coral/blob/master/src/realtime.py It should be commit #29.
Other SO questions I have examined, to no avail: Corrupted image is being saved with PIL
Any help would be greatly appreciated!
I fixed the problem by editing this line:
temp_image_object = PIL.Image.open(temperature_file)
to be
temp_image_object = PIL.Image.open(temperature_file).convert('RGB')

segment object(leaf) which is on the white paper using image processing

I want to get only leaf from an image.
The background is a normal white paper(A4) and there is some shadow.
I apply some method (structure element,edge detection using filter) but I cannot find the general way which can apply all the image.
these are examples.
Are there better methods for this problem??
thank you
another example.
and the result I got is
By using
hsv_I = rgb2hsv(I);
Is = hsv_I(:,:,2);
Is_d = imdilate(Is,strel('diamond',4));
Is_e = imerode(Is,strel('diamond',2));
Is_de = imerode(Is_d,strel('disk',2));
Is_def = imfill(Is_de,'holes');
Is_defe = imerode(Is_def,strel('disk',5));
Then Is_defe is a mask to segment
But the method that i did is very specific. I cannot use this in general.
If you have the Image Processing Toolbox, you could do as follows:
The code below first estimates the threshold with the function graythresh, thresholds the image and fills holes with the imfill function. Suppose I is a cell containing your RGB images:
for k=1:length(I)
t=graythresh(rgb2gray(I{k}));
BW{k}=imfill(~im2bw(I{k}, t), 'holes');
subplot(length(I),1,k), imshow(BW{k});
end

Converting a grayscale image to black and white

I have a grayscale image that only has the values 60 and 117. How can I convert the image to only black and white without graylevels?
I tried the matlab function gray2ind, but didn't get the expected output.
Thanks.
Try im2bw(img, level) with level = 0.5.
This is a matlab function that takes a grayscale image img, applies a threshold of level (a value between [0,1]) and returns a black and white image.
This function is part of the Image Processing Toolbox. Your case is simple enough that you could also try something like:
bwImg = false(size(img));
bwImg(img == 117) = true;
I edited the above to set values equal to false/true to more closely mimic Matlab's im2bw() which returns a matrix of logical values rather than ints.
2nd Edit: Modified the code block to reflect improvements suggested by #Amro

Resources