To convert a grayscale image to RGB image using PIL - python-imaging-library

I am trying a code to convert a grayscale image to a RGB image format in python, but, a TypeError is raised every time I try to execute it.
My code is as follows:
from PIL import Image
path = "bw.jpg"
img = Image.open(path)
rgb = img.convert("RGB")
width,height = rgb.size
for x in range(width):
for y in range(height):
r, g, b = img.getpixel((x, y))
value = r* 299.0/1000 + g* 299.0/1000 + b * 299.0/1000
value = int(value)
rgb.putpixel ((x, y), value)
rgb.save("abc.png")
The error that I get is:
r, g, b = img.getpixel((x, y))
TypeError: 'int' object is not iterable
Any assistance would be really appreciable.

You are confusing the images and the values. With img you get the greylevels, so you should use this:
grey = img.getpixel((x, y))
or, because you convert img to rgb (with RGB values), you could also write:
r, g, b = rgb.getpixel((x, y))
But then, it seems you are going doing unneeded calculations (ok, probably this was just the broken part of the complete code).
The error: img.getpixel() will return a number (on BW images), and int is not iterable to be split into r, g, and b, so the error. But rgb.getpixel() return a list (length 3), which is iterable.

Related

Julia Flux double inference issue

Recently I found that Julia lang become more powerful and it's time to revisit it again. But in every tutorial, I found the same problem with double inference - for each batch you have to calculate the model to get gradients and then recalculate it to get the loss and other metrics. This seems ridiculous and it must be a way out. Can I get model prediction and its loss before gradients update step without recalculation? Here I made an example for MLP and MNIST
using Flux, Flux.Data.MNIST, Statistics
using Flux: onehotbatch, onecold, crossentropy
using Flux.Optimise: update!
using Flux.Data: DataLoader
using Printf
X = hcat(float.(reshape.(MNIST.images(), :))...) |> gpu
Y = onehotbatch(MNIST.labels(), 0:9) |> gpu
m = Chain(
Dense(784, 32, relu),
Dense(32, 32, relu),
Dense(32, 10),
softmax
) |> gpu
loss(ŷ, y) = Flux.crossentropy(ŷ, y)
accuracy(x, y) = mean(onecold(cpu(x)) .== onecold(cpu(y)))
dl = DataLoader(X, Y, batchsize=128)
ps = params(m)
opt = Descent(0.1)
#progress for i = 1:10
#info "Epoch $i"
for (x, y) in dl
gs = gradient(ps) do
loss(m(x), y)
end
update!(opt, ps, gs)
end
vloss, vacc = [], []
for (x,y) in dl
ŷ = m(x)
l = loss(ŷ, y)
push!(vloss, l)
push!(vacc, accuracy(ŷ, y))
end
#printf "Train :: loss: %-5f acc: %-5f\n" mean(vloss) mean(vacc)
end
By the way backward-mode AD works, you get the so called "forward value" back anyway every time you calculate a gradient. If you look at how gradient is defined in Zygote, you see that you can use pullback to get both at the same time:
function value_and_gradient(f, args...)
y, back = pullback(f, args...)
return y, back(sensitivity(y))
end
sensitivity is just one, or an error for non-differentiable output types.

Getting a not enough input arguments error

I'm trying to plot the Yukawa Potential in Matlab and I want to have my program go through user inputs for the values alpha (called alph in my program) and l. The values I need to use are 0.1, 0.2 and 0.3 for alpha with values of 0, 1 and 2 of l for each value of alpha. I know I could set up a loop for this but it doesn't have to be pretty and I want to test the values one at a time. Anyway I keep getting an error after I input the values for alpha, the error I keep getting is in my function, saying that I don't have enough input arguments. The output should be the T matrix, the Hamiltonian matrix and a plot of the first 10 eigenfunctions.
I've tried going in and simply defining alpha as the numbers I want to look at and the program works fine with displaying the output I'm looking for. I just want to be able to change the values for alpha without having to change the program itself. I haven't had any problems with the l inputs.
r = linspace(0.05,19.95,1999)
n = 1999
dr = 0.05
a = full(gallery("tridiag",n,1,-2,1))
T = -0.5*a/(dr^2)
l = input('Input a value for l.')
alph = input('Input a value for alpha.')
v = arrayfun(#(r) yuk_pot(r,l),r);
V = diag(v)
H = T + V
[O,D] = eig(H);
plot(r,O(:,1),r,O(:,2),r,O(:,3),r,O(:,4),r,O(:,5),r,O(:,6),r,O(:,7),r,O(:,8),r,O(:,9),r,O(:,10))
function v = yuk_pot(r,alph,l)
v = (-exp(-alph*r)/r) + 0.5*(l*(l+1)/(r^2));
end
your function function v = yuk_pot(r,alph,l) has 3 input arguments.
you call it with 2 arguments (r and l)
v = arrayfun(#(r) yuk_pot(r,l),r);
what about the second alph argument?

How to use interpn?

I am trying to use interpn (in python using Scipy) to replicate results from Matlab using interp3. However, I am struggling to structure my arguments. I tried the following line:
f = interpn(blur_maps, fx, fy, pyr_level)
Where blur maps is a 600 x 800 x 7 representing a grayscale image at seven levels of blur,
fx and fy are indices of the seven maps. Both fx and fy are 2d arrays. pyr_level is a 2d array that contains values from 1 to 7 representing the blur map to be interpolated.
My question is since I incorrectly arranged the arguments, how can I arrange them in a way that works? I tried to look up examples but I didn't see anything similar. Here is an example of the data I am trying to interpolate:
import numpy as np
import cv2, math
from scipy.interpolate import interpn
levels = 7
img_path = '/Users/alimahdi/Desktop/i4.jpg'
img = cv2.cvtColor(cv2.imread(img_path), cv2.COLOR_BGR2GRAY)
row, col = img.shape
x_range = np.arange(0, col)
y_range = np.arange(0, row)
fx, fy = np.meshgrid(x_range, y_range)
e = np.exp(np.sqrt(fx ** 2 + fy ** 2))
pyr_level = 7 * (e - np.min(e)) / (np.max(e) - np.min(e))
blur_maps = np.zeros((row, col, levels))
blur_maps[:, :, 0] = img
for i in range(levels - 1):
img = cv2.pyrDown(img)
r, c = img.shape
tmp = img
for j in range(int(math.log(row / r, 2))):
tmp = cv2.pyrUp(tmp)
blur_maps[:, :, i + 1] = tmp
pixelGrid = [np.arange(x) for x in blur_maps.shape]
interpPoints = np.array([fx.flatten(), fy.flatten(), pyr_level.flatten()])
interpValues = interpn(pixelGrid, blur_maps, interpPoints.T)
finalValues = np.reshape(interpValues, fx.shape)
I am now getting the following error: ValueError: One of the requested xi is out of bounds in dimension 0 I do know that the problem is in interpPoints but I am not sure how to fix it. Any suggestions?
The documentation for scipy.interpolate.interpn states that the first argument is a grid of the data you are interpolating over (which is just the integers of the pixel numbers), second argument is data (blur_maps) and third arguments is the interpolation points in the form (npoints, ndims). So you would have to do something like:
import scipy.interpolate
pixelGrid = [np.arange(x) for x in blur_maps.shape] # create grid of pixel numbers as per the docs
interpPoints = np.array([fx.flatten(), fy.flatten(), pyr_level.flatten()])
# interpolate
interpValues = scipy.interpolate.interpn(pixelGrid, blur_maps, interpPoints.T)
# now reshape the output array to get in the original format you wanted
finalValues = np.reshape(interpValues, fx.shape)

Applying threshold to an image

I am trying to write a function that thresholds a grey-level image F and a threshold value t (0 ≤ t ≤ 255) such that r = 0 for r < t and r = 255 otherwise.
I have tried to implement this, but imshow(r) does not produce an output.
function f = imgThreshold(img, t)
f = img;
if (f < t)
f = 0;
else
f = 1;
end
img = imread('https://i.stack.imgur.com/kP0u2.png');
t = 20;
r = imgThreshold(img, t);
imshow(r);
This should threshold this image. However, it does not do so. What am I doing wrong?
Best would be to use logical indexing:
f(f<t)=0; % set all elements of f<t to 0
f(~(f==0))=1; % Set all elements where f is not 0 (i.e. the rest) to 1
f<t nicely produces a logical matrix adhering to the condition, but subsequently you do either f=1 or f=0, meaning that you set the entirety of f to be a scalar (one or zero), which of course just plots a black or white square. Instead, use the logical matrix as indexing operation into the matrix itself, then assigning the desired value to each true entry, like above.
Also a function definition either goes in its own file, or on the bottom of the script. Thus either you save the function as imgThreshold.m and leave the rest for the script, or first call the script and place function f = imgThreshold(img, t) etc after the call to imshow

G and GHAT need to be same classification tree

Can someone help to solve and if possible explain my mistake.
I have a two numeric matrices for using it in classification tree
x: data matrix <2422x39 double>
y: column vector, class label for each instance <2422x1 double>
I'm doing:
t = classregtree(x, y, 'method','classification');
yPredicted = eval(t, x);
cm = confusionmat(y,yPredicted); // error
Error using ==> confusionmat at 52
G and GHAT need to be the same type.
Tree succesfully built. But I cannot get a confusion matrix for that example
I have read that post to write above code Decision Tree in Matlab
If I use exactly same example from link, its working but when I use my own its not working.
Same steps I took for building regression tree ( t = classregtree(x, y) ) and no error in confusionmat() function.
Please explain what I'm doing incorrectly.
Thanks in advance
It seems to me in your case, eval(t,x) returns cells of char type, while your x and y come with "double" type instead of "char".
The reason the code in Decision Tree in Matlab works is because:
y = strcat(Origin,{});
returns y that is a cell with "char". Thus the argument G and GHAT have the same type.
So, select one that suits your problem:
Approach A: convert yPredicted to numeric matrix
Edit this line :
yPredicted = eval(t, x);
to :
yPredicted = str2num( cell2mat( eval(t, x) ) );
Approach B: convert y to cell of char before calling confusionmat()
y = num2cell( num2str(y) )