I'm trying to unblur the blurred segments of the following picture.
the original PSF was not given, so I proceeded to analyze the blurred part and see whether there was a word I could roughly make out. I found out that I could make out "of" in the blurred section. I cropped out both the the blurred "of" and its counterpart in the clear section, as seen below.
I then thought through lectures in FFT that you divide the blurred (frequency domain) with a particular blurring function (frequency domain) to recreate the original image.
I thought that if I could do Unblurred (frequency domain) \ Blurred(frequency domain), the original PSF could be retrieved. Please advise on how I could do this.
Below is my code:
img = im2double(imread('C:\Users\adhil\Desktop\matlab pics\image1.JPG'));
Blurred = imcrop(img,[205 541 13 12]);
Unblurred = imcrop(img,[39 140 13 12]);
UB = fftshift(Unblurred);
UB = fft2(UB);
UB = ifftshift(UB);
F_1a = zeros(size(B));
for idx = 1 : size(Blurred, 3)
B = fftshift(Blurred(:,:,idx));
B = fft2(B);
B = ifftshift(B);
UBa = UB(:,:,idx);
tmp = UBa ./ B;
tmp = ifftshift(tmp);
tmp = ifft2(tmp);
tmp = fftshift(tmp);
[J, P] = deconvblind(Blurred,tmp);
end
subplot(1,3,1);imshow(Blurred);title('Blurred');
subplot(1,3,2);imshow(Unblurred);title('Original Unblurred');
subplot(1,3,3);imshow(J);title('Attempt at unblurring');
This code, however, does not work, and I'm getting the following error:
Error using deconvblind
Expected input number 2, INITPSF, to be real.
Error in deconvblind>parse_inputs (line 258)
validateattributes(P{1},{'uint8' 'uint16' 'double' 'int16' 'single'},...
Error in deconvblind (line 122)
[J,P,NUMIT,DAMPAR,READOUT,WEIGHT,sizeI,classI,sizePSF,FunFcn,FunArg] = ...
Error in test2 (line 20)
[J, P] = deconvblind(Blurred,tmp);
Is this a good way to recreate the original PSF?
I'm not an expert in this area, but I have played around with deconvolution a little bit and have written a program to compute the point spread function when given a clear image and a blurred image. Once I got the psf function using this program, I verified that it was correct by using it to deconvolve the blurry image and it worked fine. The code is below. I know this post is extremely old, but hopefully it will still be of use to someone.
import numpy as np
import matplotlib.pyplot as plt
import cv2
def deconvolve(normal, blur):
blur_fft = np.fft.rfft2(blur)
normal_fft = np.fft.rfft2(normal)
return np.fft.irfft2(blur_fft/(normal_fft))
img = cv2.imread('Blurred_Image.jpg')
blur = img[:,:,0]
img2 = cv2.imread('Original_Image.jpg')
normal = img2[:,:,0]
psf_real = deconvolve(normal, blur)
fig = plt.figure(figsize=(10,4))
ax1 = plt.subplot(131)
ax1.imshow(blur)
ax2 = plt.subplot(132)
ax2.imshow(normal)
ax3 = plt.subplot(133)
ax3.imshow(psf_real)
plt.gray()
plt.show()
Related
I have a clean image, and a noisy image. I created a denoiser and applied it to the noisy image, that was my final output. Now to compare how much this image is close to a clean image I need to compare it using PSNR and SSIM, but due to different positions of the image I am unable to compare.
Now I am getting SSIM as 0.5, which is very low, due to the improper placement of both the images. If the images are registered properly, then I guess SSIM should come around 0.80+. But I have not been able to accomplish this.
How can I align these two images to obtain a good SSIM value?
I have two coin images, 1st image (CLEAN), 2nd image (IMPROVED a NOISY IMG), for comparison.
Clean Img:
Noisy Img:
Due to positions of images at different positions ssim(img1,img2) is giving incorrect output. I tried cropping but that did not work.
Here is what I have tried so far:
Attempt 1:
function [valPSNR,valSSIM,badpict]=getSSIM(clean_img,img2)
% pad reference image since object is so close to edges
refpict = padarray(mat2gray(clean_img),[20 20],'replicate','both');
% crop test image down to extract the object alone
badpict = imcrop(mat2gray(img2),[2.5 61.5 357 363]);
% maximize normalized cross-correlation to find offset
szb = size(badpict);
c = normxcorr2(badpict,refpict);
[idxy idxx] = find(c == max(c(:)));
osy = idxy-szb(1);
osx = idxx-szb(2);
% crop the reference pict to the ROI
refpict = refpict(osy:idxy-1,osx:idxx-1);
%imshow(imfuse(badpict,refpict,'checkerboard'));
%imagesc(badpict);
valSSIM=ssim(badpict,refpict);
valPSNR=getPSNR(badpict,refpict);
img2=badpict;
clean_img=refpict;
figure; imshowpair(clean_img,img2);
figure; montage({mat2gray(clean_img),mat2gray(img2)}, 'Size', [1 2], 'BackgroundColor', 'w', 'BorderSize', [2 2]);
end
Attempt 2:
function [valPSNR,valSSIM,badpict]=getSSIM2(clean_img,img2)
% pad reference image since object is so close to edges
bw1 = im2bw(mat2gray(clean_img));
bw2 = imclose(im2bw(mat2gray(img2),0.3),strel('disk',9));
bw2 = bwareafilt(bw2,1);
% make same size
[r,c] = find(bw1);
clean_img = clean_img(min(r):max(r),min(c):max(c));
[r,c] = find(bw2);
img2 = img2(min(r):max(r),min(c):max(c));
img2= imresize(img2, size(clean_img),'bilinear');
valPSNR=getPSNR(mat2gray(clean_img),mat2gray(img2));
valSSIM=ssim(mat2gray(clean_img),mat2gray(img2));
badpict=img2;
figure; imshowpair(clean_img,img2);
figure; montage({mat2gray(clean_img),mat2gray(img2)}, 'Size', [1 2], 'BackgroundColor', 'w', 'BorderSize', [2 2]);
end
As others have pointed out, the resampling required by registration will have some non-zero error. But, here is some sample code that will take you through the registration part that is the crux of your question.
% SSIM isn't defined on RGB images, convert to grayscale.
ref = rgb2gray(imread('https://i.stack.imgur.com/tPKEJ.png'));
X = rgb2gray(imread('https://i.stack.imgur.com/KmU4y.png'));
% The input image data has bright borders at the edges that create
% artifacts in resampling, best to just crop those or maybe there are
% aquisitions that don't have these borders?
X = X(3:end-2,3:end-2);
ref = ref(4:end-3,4:end-3);
figure
montage({X,ref});
tform = imregcorr(X,ref,"translation");
Xreg = imwarp(X,tform,OutputView=imref2d(size(ref)),SmoothEdges=true);
figure
imshowpair(Xreg,ref)
ssim(Xreg,ref)
Maybe you can refer to my github.
I implemented a template matching algorithm by OpenCV which you can use NCC-Based Pattern Matching to find targets, and then get a score (similarity).
You can then use this score to decide if it is clean.
Besides, tranforming c++ code may be an issue for you, but just find the all corresponded function in matlab version.
Here are effects (red blocks are areas with similarity higher than threshold 0.85 in comparison with golden sample):
The whole function is too long to be posted here.
Part of the function:
for (int i = 0; i < iSize; i++)
{
Mat matRotatedSrc, matR = getRotationMatrix2D (ptCenter, vecAngles[i], 1);
Mat matResult;
Point ptMaxLoc;
double dValue, dMaxVal;
double dRotate = clock ();
Size sizeBest = GetBestRotationSize (vecMatSrcPyr[iTopLayer].size (), pTemplData->vecPyramid[iTopLayer].size (), vecAngles[i]);
float fTranslationX = (sizeBest.width - 1) / 2.0f - ptCenter.x;
float fTranslationY = (sizeBest.height - 1) / 2.0f - ptCenter.y;
matR.at<double> (0, 2) += fTranslationX;
matR.at<double> (1, 2) += fTranslationY;
warpAffine (vecMatSrcPyr[iTopLayer], matRotatedSrc, matR, sizeBest);
MatchTemplate (matRotatedSrc, pTemplData, matResult, iTopLayer);
minMaxLoc (matResult, 0, &dMaxVal, 0, &ptMaxLoc);
vecMatchParameter[i * (m_iMaxPos + MATCH_CANDIDATE_NUM)] = s_MatchParameter (Point2f (ptMaxLoc.x - fTranslationX, ptMaxLoc.y - fTranslationY), dMaxVal, vecAngles[i]);
for (int j = 0; j < m_iMaxPos + MATCH_CANDIDATE_NUM - 1; j++)
{
ptMaxLoc = GetNextMaxLoc (matResult, ptMaxLoc, -1, pTemplData->vecPyramid[iTopLayer].cols, pTemplData->vecPyramid[iTopLayer].rows, dValue, m_dMaxOverlap);
vecMatchParameter[i * (m_iMaxPos + MATCH_CANDIDATE_NUM) + j + 1] = s_MatchParameter (Point2f (ptMaxLoc.x - fTranslationX, ptMaxLoc.y - fTranslationY), dValue, vecAngles[i]);
}
}
FilterWithScore (&vecMatchParameter, m_dScore-0.05*iTopLayer);
I'm relatively new to Matlab, and trying to understand why a piece of code isn't working.
I have a 512x512 image that needs to be downsized to 256, and then resized back up to 512.
How I understand the mathematics, is that I would need to mean the pixels in the image to get the 256, and then sum them back to get the 512. Is that correct ? Following is the code that I'm looking at, and if someone can explain me whats wrong(its giving a blank white image), I would appreciate it:
w = double(imread('walkbridge.tif'));
%read the image
w = w(:,:,1);
for x = 1:256
for y = 1:256
s256(x,y) = (w(2*x,2*y)+ w(2*x,(2*y)-1) + w((2*x)-1,2*y)+ w((2*x)-1,(2*y)-1))/4;
end
end
for x = 1 : 256
for y = 1 : 256
for x1 = 0:1
for y1 = 0:1
R1((2*x)-x1,((2*y)-y1)) = s256(x,y);
end
end
end
end
imshow(R1)
I got your code to work, so you might have some bad values in your image data. Namely, if your image has values in range 0..127 or something similar, it will most likely show as all white. By default, imshow expects color channels to be in range 0..1.
You might also want to simplify your code a bit by indexing the original array instead of accessing individual elements. That way the code is even easy to change:
half_size = 256;
w = magic(2*half_size);
w = w / max(w(:));
figure()
imshow(w)
s = zeros(half_size);
for x = 1:half_size
for y = 1:half_size
ix = w(2*x-1:2*x, 2*y-1:2*y);
s(x,y) = sum(ix(:))/4;
end
end
for x = 1:half_size
for y = 1:half_size
R1(2*x-1:2*x, 2*y-1:2*y) = s(x,y);
end
end
figure()
imshow(R1)
I imagine the calculations could even be vectorised in some way instead of looping, but I didn't bother.
I have a picture in MATLAB and decompositioned it to R, G and B channel.
And now I need to figure out resolution, median, upper and lower quartil, interquartil span and modus.
Here is the code I use for it:
close all; clc; clear all
I = imread('image_S006_I0000.jpg');
imshow(I)
[R S T] = size(I);
Red(:,:,1)=I(:,:,1);
Red(:,:,2)=zeros(R,S);
Red(:,:,3)=zeros(R,S);
Green(:,:,1)=zeros(R,S);
Green(:,:,2)=I(:,:,1);
Green(:,:,3)=zeros(R,S);
Blue(:,:,1)=zeros(R,S);
Blue(:,:,2)=zeros(R,S);
Blue(:,:,3)=I(:,:,1);
OR
Red=double(I(:,:,1));
Red=zeros(R,S);
Red=zeros(R,S);
Green=zeros(R,S);
Green=double(I(:,:,1));
Green=zeros(R,S);
Blue=zeros(R,S);
Blue=zeros(R,S);
Blue=double(I(:,:,1));
OR
Red(:,:,1)=double(I(:,:,1));
Green(:,:,1)=double(I(:,:,1));
Blue(:,:,1)=double(I(:,:,1));
cat(3, uint8(Red), zeros(R, S), zeros(R, S));
others = zeros(R, S);
red_plt = cat(3, uint8(Red), others, others);
green_plt = cat(3, others, uint8(Green), others);
blue_plt = cat(3, others, others, uint8(Blue));
figure()
subplot(131);imshow(red_plt)
subplot(132);imshow(green_plt)
subplot(133);imshow(blue_plt)
NOW PLOTTITG (It doesn't print it in Red, Green and Blue color. First two
are just all black, the third one is black and white):
figure()
subplot(131);imshow(uint8(Red))
subplot(132);imshow(uint8(Green))
subplot(133);imshow(uint8(Blue))
[x1 y1 z1] = size(I);
% MEDIAN.
imgmedianR = median (Red(:))
imgmedianG = median (Green(:))
imgmedianB = median (Blue(:))
%QUARTIL
r025 = quantile(Red,0.25)
r075 = quantile(Red,0.75)
g025 = quantile(Green,0.25)
g075 = quantile(Green,0.75)
b025 = quantile(Blue,0.25)
b075 = quantile(Blue,0.75)
%INTERQUARTIL SPAN
r_iqr = iqr(Red)
g_iqr = iqr(Green)
b_iqr = iqr(Blue)
modus_Red = mode(Red(:))
modus_Green = mode(Green(:))
modus_Blue = mode(Blue(:))
MEDIAN: When I try to count MEDIAN, it gives me a bunch of numbers (actually matlab prints out a number for each column separately).
What have I done wrong there?
QUARTIL: The same problem as I have in code for MEDIAN. What have I done wrong there?
INTERQUARTIL SPAN: Matlab prints out subsequent error:
Mixed integer class inputs are not supported.
What have I done wrong?
RESOLUTION: I need to find out a resolution of the image using Matlab. I have tried out funciton imfinfo, but the info isn't included. How can I find such an information using any kind of Matlab function?
Thank you very much in advance!
You save every separate colour in a 3d matrix. This is not nessecary. So save them in a 2d matrix as follows:
Red=double(I(:,:,1));
Green=double(I(:,:,2));
Blue=double(I(:,:,3));
Note there is a conversion to double. That's needed for the iqr. Also use in every function Red(:) instead of Red (same for other colours of course). If you change all that, it should work just fine.
Concerning the resolution, that is just the number of pixels for the height and the width, in your case R and S.
ps you're calling size(I) twice.
In case of plotting the red, green and blue separately, you need to make the same matrix as the original, with exception that only 1 colour is non-zero. The image is a RxSx3 matrix. So if you want to plot the red part you need to make an RxSx3 matrix where only red is non-zero:
cat(3, uint8(Red), zeros(R, S), zeros(R, S));
So in total it should look like this
others = zeros(R, S);
red_plt = cat(3, uint8(Red), others, others);
green_plt = cat(3, others, uint8(Green), others);
blue_plt = cat(3, others, others, uint8(Blue));
figure()
subplot(131);imshow(red_plt)
subplot(132);imshow(green_plt)
subplot(133);imshow(blue_plt)
EDIT:
The whole code:
I = imread('image_S006_I0000.jpg');
imshow(I)
[R S T] = size(I);
Red=double(I(:,:,1));
Green=double(I(:,:,2));
Blue=double(I(:,:,3));
others = zeros(R, S);
red_plt = cat(3, uint8(Red), others, others);
green_plt = cat(3, others, uint8(Green), others);
blue_plt = cat(3, others, others, uint8(Blue));
figure()
subplot(131);imshow(red_plt)
subplot(132);imshow(green_plt)
subplot(133);imshow(blue_plt)
% MEDIAN.
imgmedianR = median (Red(:))
imgmedianG = median (Green(:))
imgmedianB = median (Blue(:))
%QUARTIL
r025 = quantile(Red(:),0.25)
r075 = quantile(Red(:),0.75)
g025 = quantile(Green(:),0.25)
g075 = quantile(Green(:),0.75)
b025 = quantile(Blue(:),0.25)
b075 = quantile(Blue(:),0.75)
%INTERQUARTIL SPAN
r_iqr = iqr(Red(:))
g_iqr = iqr(Green(:))
b_iqr = iqr(Blue(:))
modus_Red = mode(Red(:))
modus_Green = mode(Green(:))
modus_Blue = mode(Blue(:))
i am currently doing a case study on the improved performance of a separable filter vs that of a square filter. I understand the mathematics behind the time complexity difference, however i have run into a problem with the real world implementation.
so basically what i have done is write a loop which implements my filter image function given by:
function imOut = FilterImage(imIn, kernel, boundFill, outputSize)
VkernelOffset = floor(size(kernel,1)/2);
HkernelOffset = floor(size(kernel,2)/2);
imIn = padarray(imIn, [VkernelOffset HkernelOffset], boundFill);
imInPadded = padarray(imIn, [VkernelOffset HkernelOffset], boundFill);
imOut = zeros(size(imIn));
kernelVector = reshape(kernel,1, []);
kernelVector3D = repmat(kernelVector, 1, 1, size(imIn,3));
for row = 1:size(imIn,1)
Vwindow = row + size(kernel,1)-1;
for column = 1:size(imIn,2)
Hwindow = column + size(kernel,2)-1;
imInWindowVector = reshape( ...
imInPadded(row:Vwindow, column:Hwindow, :),1,[],size(imIn,3));
imOut(row,column, :) = sum((imInWindowVector.*kernelVector3D),2);
end
end
ouputSize = lower(outputSize);
if strcmp(outputSize, 'same')
imOut = imOut((1+VkernelOffset):(size(imOut,1)-VkernelOffset), ...
(1+HkernelOffset):(size(imOut,2)-HkernelOffset), : );
elseif strcmp(outputSize, 'valid')
imOut = imOut((1+VkernelOffset*2):(size(imOut,1)-VkernelOffset*2), ...
(1+HkernelOffset*2):(size(imOut,2)-HkernelOffset*2), : );
end
end
I wrote another script which carries out the following two sets of commands on a 740x976 greyscale image and logs their processing time:
for n = 1:25
dim(n) = 6*n + 1;
h=fspecial('gaussian',dim(n), 4);
tic;
Im = FilterImage(I,h,0,'full');
tM(n) = toc;
h1 = fspecial('gaussian', [dim(n) 1], 4);
h2 = fspecial('gaussian', [1 dim(n)], 4);
tic;
It = FilterImage(I,h1,0,'full');
Is = FilterImage(It,h2,0,'full');
tS(n) = toc;
end
after plotting the respective time required i get the following result:
My problem is, Why is the separable method slower up to kernel matrices of size 49x49, and only shows improved speed from kernel sizes of 55x55 upwards, is something wrong with my image filter code?
p.s. the image filter code was designed for 3D images to take into account colour depth, however for the speed test i am using a greyscale image converted to double using im2double.
p.s.2 so as mentioned below, for comparison i carried out the same process using MATLAB's native conv2 function, and the results where as you'd expect, and also incredibly faster...
thanks
It seems like an optimization error.
I'd use the function conv2 instead.
Let's write a sample code:
mOutputImage = conv2((vFilterCoeff.' * vFilterCoeff), mInputImage);
mOutputImageSep = conv2(vFilterCoeff, vFilterCoeff.', mInputImage);
Try those in a loop where the length of vFilterCoeff (Row Vector!!!) is getting bigger.
update us what are the result now.
I am trying to execute this function for image reconstruction where
ra, rh, rv, rd are reconstructed coefficients. but i am facing problem in addition and subtraction.
Please help.
Xhat = ra2 + rh2 + rv2 + rd2 + rh1 + rv1 + rd1;
sprintf('Reconstruction error (using wrcoef2) = %g', max(max(abs(X-Xhat))))
OR
XXhat = waverec2(wc,s,wname);
sprintf('Reconstruction error (using waverec2) = %g', max(max(abs(X-XXhat)))
I decomposed the image using:
>> a1 = appcoef2(wc,s,wname,1);
>> h1 = detcoef2('h',wc,s,1);
>> v1 = detcoef2('v',wc,s,1);
>> d1 = detcoef2('d',wc,s,1);
>> a2 = appcoef2(wc,s,wname,2);
>> h2 = detcoef2('h',wc,s,2);
>> v2 = detcoef2('v',wc,s,2);
>> d2 = detcoef2('d',wc,s,2);
Then reconstructed using above parameters.
Now i have to comnbine them.
I'm guessing your problem is almost certainly at the abs(X-Xhat) line.
Why? You seem to be doing some sort of wavelet decomposition/reconstruction, and if you don't pass in the right parameters your output may be larger than the original image. Therefore it makes no sense to ask for X-Xhat if these are of different sizes and you will get an error message.
The best way of fixing this is to when you reconstruct (presumably using upcoef2), is to pass size as an additional parameter to truncate. A truncated (heh) and adjusted example from the docs:
load woman;
[c,s] = wavedec2(X,2,'db4');
siz = s(size(s,1),:);
ca1 = appcoef2(c,s,'db4',1);
a = upcoef2('a',ca1,'db4',1,siz);
a2 = upcoef2('a',ca1,'db4',1);
You'll see that size(X) and size(a) are both 256 x 256, but size(a2) is larger. Therefore a-X is fine and a2-X will give you a "Matrix dimensions must agree." error.