imfindcircles not finding obvious circle - matlab

I've tried the examples on the imfindcircles documentation which use much more complicated images and they worked fine. But in the following code which generates a perfect centered circle and attempts to find it with imfindcircles I get an empty result. I've been playing around with the parameters for imfindcircles, including ObjectPolarity, Sensitivity, and a radii range, but I've yet to get anything other than an empty result.
function annulusConvolve()
function outputImg = generateCircle2(circleRadius)
padding = 200;
[xmesh, ymesh] = meshgrid(-circleRadius-padding:circleRadius+padding, -circleRadius-padding:circleRadius+padding);
outputImg = zeros(size(xmesh));
outputImg((xmesh.^2 + ymesh.^2) < circleRadius^2) = 1;
end
testPicture = generateCircle2(200);
figure;
imshow(testPicture);
centers = imfindcircles(testPicture,200)
end

worked ok for me if you try your example with:
centers = imfindcircles(testPicture,[195 205],'Sensitivity',0.99)

Related

Matlab - Removing image background using normalization

I have an image like this:
my goal is to get the output under background normalization at this link.
Following the above link, I did the following:
(1). I first dilate the image to get the background
(2). then try to remove it via normalization
I got the background:
However, when I try to do the normalized division, I get this :
(black borders added to make clear of the boundary of the image)
this is my code:
image = imread('image.png');
image = rgb2gray(image);
se = offsetstrel('ball',9,9);
dilatedI = imdilate(image,se);
output = imdivide(image,dilatedI);
imshow(output,[]);
using
imshow(output)
just gives a black image.
I thought it might be a type conversion issue, but based on the resources mentioned earlier, I am uncertain if it is the case...
Any advice would be appreciated
Just make sure you dont do integer division! your images are integer type, so 4/5 returns 0 and 5/4 returns 1, not a floating point number. Just convert to float before dividing:
image = imread('https://i.stack.imgur.com/bIVRT.png');
%image = rgb2gray(image); The image is not a RGB online
se = offsetstrel('ball',21,21);
dilatedI = imdilate(image,se);
output = imdivide(double(image),double(dilatedI));
figure
subplot(121)
imshow(image);
subplot(122)
imshow(output);

Smooth and fit edge of binary images

i am working on a research about the swimming of fishes using analysis of videos, then i need to be carefully with the images (obtained from video frames) with emphasis in the tail.
The images are in High-Resolution and the software that i customize works with binary images, because is easy to use maths operations on this.
For obten this binary images i use 2 methods:
1)Convert the image to gray, invert the colors,later to bw and finally to binary with a treshold that give me images like this, with almost nothing of noise. The images sometimes loss a bit of area and doesn't is very exactly with the tail(now i need more acurracy for determinate the amplitude of tail moves)
image 1
2)i use this code, for cut the border that increase the threshold, this give me a good image of the edge, but i dont know like joint these point and smooth the image, or fitting binary images, the app fitting of matlab 2012Rb doesn't give me a good graph and i don't have access to the toolboxs of matlab.
s4 = imread('arecorte.bmp');
A=[90 90 1110 550]
s5=imcrop(s4,A)
E = edge(s5,'canny',0.59);
image2
My question is that
how i can fit the binary image or joint the points and smooth without disturb the tail?
Or how i can use the edge of the image 2 to increase the acurracy of the image 1?
i will upload a image in the comments that give me the idea of the method 2), because i can't post more links, please remember that i am working with iterations and i can't work frame by frame.
Note: If i ask this is because i am in a dead point and i don't have the resources to pay to someone for do this, until this moment i was able to write the code but in this final problem i can't alone.
I think you should use connected component labling and discard the small labels and than extract the labels boundary to get the pixels of each part
the code:
clear all
% Read image
I = imread('fish.jpg');
% You don't need to do it you haef allready a bw image
Ibw = rgb2gray(I);
Ibw(Ibw < 100) = 0;
% Find size of image
[row,col] = size(Ibw);
% Find connceted components
CC = bwconncomp(Ibw,8);
% Find area of the compoennts
stats = regionprops(CC,'Area','PixelIdxList');
areas = [stats.Area];
% Sort the areas
[val,index] = sort(areas,'descend');
% Take the two largest comonents ids and create filterd image
IbwFilterd = zeros(row,col);
IbwFilterd(stats(index(1,1)).PixelIdxList) = 1;
IbwFilterd(stats(index(1,2)).PixelIdxList) = 1;
imshow(IbwFilterd);
% Find the pixels of the border of the main component and tail
boundries = bwboundaries(IbwFilterd);
yCorrdainteOfMainFishBody = boundries{1}(:,1);
xCorrdainteOfMainFishBody = boundries{1}(:,2);
linearCorrdMainFishBody = sub2ind([row,col],yCorrdainteOfMainFishBody,xCorrdainteOfMainFishBody);
yCorrdainteOfTailFishBody = boundries{2}(:,1);
xCorrdainteOfTailFishBody = boundries{2}(:,2);
linearCorrdTailFishBody = sub2ind([row,col],yCorrdainteOfTailFishBody,xCorrdainteOfTailFishBody);
% For visoulaztion put color for the boundries
IFinal = zeros(row,col,3);
IFinalChannel = zeros(row,col);
IFinal(:,:,1) = IFinalChannel;
IFinalChannel(linearCorrdMainFishBody) = 255;
IFinal(:,:,2) = IFinalChannel;
IFinalChannel = zeros(row,col);
IFinalChannel(linearCorrdTailFishBody) = 125;
IFinal(:,:,3) = IFinalChannel;
imshow(IFinal);
The final image:

Matlab radial gradient image

I am attempting to create a radial gradient image to look like the following using Matlab. The image needs to be of size 640*640*3 as I have to blend it with another image of that size. I have written the following code but the image that prints out is simply a grey circle on a black background with no fading around the edges.
p = zeros(640,640,3);
for i=1:640
for j=1:640
d = sqrt((i-320)^2+(j-320)^2);
if d < 640/3
p(i,j,:) = .5;
elseif d > 1280/3
p(i,j,:) = 0;
else
p(i,j,:) = (1 + cos(3*pi)*(d-640/3))/4;
end
end
end
imshow(p);
Any help would be greatly appreciated as I am new to Matlab.
Change:
p(i,j,:) = (1 + cos(3*pi)*(d-640/3))/4;
to
p(i,j,:) = .5-( (.5-0)*(d-640/3)/(640/3)) ;
This is an example of linear interpolation, where the grey value from the inner rim drops linearly to the background.
You can try other equations to have different kinds of gradient fading!
If you look more closely on your third case (which by the way should be a simple else instead of elseif), you can see that you have
= (1 + cos(3*pi))*...
Since cos(3*pi) = -1, this will always be 0, thus making all pixels within that range black. I assume that you would want a "d" in there somewhere.

Changing image aspect ratio of interpolated RGB image. Square to rectangular

I have some code which takes a fish eye images and converts it to a rectangular image in each RGB channels. I am having trouble with the fact the the output image is square instead of rectangular. (this means that the image is distorted, compressed horizontally.) I have tried changing the output matrix to a more suitable format, without success. Besides this i have also discovered that for the code to work the input image must be square like 500x500. Any idea how to solve this issue? This is the code:
The code is inspired by Prakash Manandhar "Polar To/From Rectangular Transform of Images" file exchange on mathworks.
EDIT. Code now works.
function imP = FISHCOLOR2(imR)
rMin=0.1;
rMax=1;
[Mr, Nr, Dr] = size(imR); % size of rectangular image
xRc = (Mr+1)/2; % co-ordinates of the center of the image
yRc = (Nr+1)/2;
sx = (Mr-1)/2; % scale factors
sy = (Nr-1)/2;
reduced_dim = min(size(imR,1),size(imR,2));
imR = imresize(imR,[reduced_dim reduced_dim]);
M=size(imR,1);N=size(imR,2);
dr = (rMax - rMin)/(M-1);
dth = 2*pi/N;
r=rMin:dr:rMin+(M-1)*dr;
th=(0:dth:(N-1)*dth)';
[r,th]=meshgrid(r,th);
x=r.*cos(th);
y=r.*sin(th);
xR = x*sx + xRc;
yR = y*sy + yRc;
for k=1:Dr % colors
imP(:,:,k) = interp2(imR(:,:,k), xR, yR); % add k channel
end
imP = imresize(imP,[size(imP,1), size(imP,2)/3]);
imP = imrotate(imP,270);
SOLVED
Input image <- Image link
Output image <- Image link
PART A
To remove the requirement of a square input image, you may resize the input image into a square one with this -
%%// Resize the input image to make it square
reduced_dim = min(size(imR,1),size(imR,2));
imR = imresize(imR,[reduced_dim reduced_dim]);
Few points I would like to raise here though about this image-resizing to make it a square image. This was a quick and dirty approach and distorts the image for a non-square image, which you may not want if the image is not too "squarish". In many of those non-squarish images, you would find blackish borders across the boundaries of the image. If you can remove that using some sort of image processing algorithm or just manual photoshoping, then it would be ideal. After that even if the image is not square, imresize could be considered a safe option.
PART B
Now, after doing the main processing of flattening out the fisheye image,
at the end of your code, it seemed like the image has to be rotated
90 degrees clockwise or counter-clockwise depending on if the fisheye
image have objects inwardly or outwardly respectively.
%%// Rotating image
imP = imrotate(imP,-90); %%// When projected inwardly
imP = imrotate(imP,-90); %%// When projected outwardly
Note that the flattened image must have the height equal to the half of the
size of the input square image, that is the radius of the image.
Thus, the final output image must have number of rows as - size(imP,2)/2
Since you are flattening out a fisheye image, I assumed that the width
of the flattened image must be 2*PI times the height of it. So, I tried this -
imP = imresize(imP,[size(imP,2)/2 pi*size(imP,2)]);
But the results looked too flattened out. So, the next logical experimental
value looked like PI times the height, i.e. -
imP = imresize(imP,[size(imP,2)/2 pi*size(imP,2)/2]);
Results in this case looked good.
I'm not very experienced in the finer points of image processing in MATLAB, but depending on the exact operation of the imP fill mechanism, you may get what you're looking for by doing the following. Change:
M = size(imR, 1);
N = size(imR, 2);
To:
verticalScaleFactor = 0.5;
M = size(imR, 1) * verticalScaleFactor;
N = size(imR, 2);
If my hunch is right, you should be able to tune that scale factor to get the image just right. It may, however, break your code. Let me know if it doesn't work, and edit your post to flesh out exactly what each section of code does. Then we should be able to give it another shot. Good luck!
This is the code which works.
function imP = FISHCOLOR2(imR)
rMin=0.1;
rMax=1;
[Mr, Nr, Dr] = size(imR); % size of rectangular image
xRc = (Mr+1)/2; % co-ordinates of the center of the image
yRc = (Nr+1)/2;
sx = (Mr-1)/2; % scale factors
sy = (Nr-1)/2;
reduced_dim = min(size(imR,1),size(imR,2));
imR = imresize(imR,[reduced_dim reduced_dim]);
M=size(imR,1);N=size(imR,2);
dr = (rMax - rMin)/(M-1);
dth = 2*pi/N;
r=rMin:dr:rMin+(M-1)*dr;
th=(0:dth:(N-1)*dth)';
[r,th]=meshgrid(r,th);
x=r.*cos(th);
y=r.*sin(th);
xR = x*sx + xRc;
yR = y*sy + yRc;
for k=1:Dr % colors
imP(:,:,k) = interp2(imR(:,:,k), xR, yR); % add k channel
end
imP = imresize(imP,[size(imP,1), size(imP,2)/3]);
imP1 = imrotate(imP1,270);

Rotation of image manually in matlab

I am trying to rotate the image manually using the following code.
clc;
m1 = imread('owl','pgm'); % a simple gray scale image of order 260 X 200
newImg = zeros(500,500);
newImg = int16(newImg);
rotationMatrix45 = [cos((pi/4)) -sin((pi/4)); sin((pi/4)) cos((pi/4))];
for x = 1:size(m1,1)
for y = 1:size(m1,2)
point =[x;y] ;
product = rotationMatrix45 * point;
product = int16(product);
newx =product(1,1);
newy=product(2,1);
newImg(newx,newy) = m1(x,y);
end
end
imshow(newImg);
Simply I am iterating through every pixel of image m1, multiplying m1(x,y) with rotation matrix, I get x',y', and storing the value of m1(x,y) in to `newImg(x',y')' BUT it is giving the following error
??? Attempted to access newImg(0,1); index must be a positive integer or logical.
Error in ==> at 18
newImg(newx,newy) = m1(x,y);
I don't know what I am doing wrong.
Part of the rotated image will get negative (or zero) newx and newy values since the corners will rotate out of the original image coordinates. You can't assign a value to newImg if newx or newy is nonpositive; those aren't valid matrix indices. One solution would be to check for this situation and skip such pixels (with continue)
Another solution would be to enlarge the newImg sufficiently, but that will require a slightly more complicated transformation.
This is assuming that you can't just use imrotate because this is homework?
The problem is simple, the answer maybe not : Matlab arrays are indexed from one to N (whereas in many programming langages it's from 0 to (N-1) ).
Try newImg( max( min(1,newX), m1.size() ) , max( min(1,newY), m1.size() ) ) maybe (I don't have Matlab at work so I can tell if it's gonna work), but the resulting image will be croped.
this is an old post so I guess it wont help the OP but as I was helped by his attempt I post here my corrected code.
basically some freedom in the implementation regarding to how you deal with unassigned pixels as well as wether you wish to keep the original size of the pic - which will force you to crop areas falling "outside" of it.
the following function rotates the image around its center, leaves unassigned pixels as "burned" and crops the edges.
function [h] = rot(A,ang)
rotMat = [cos((pi.*ang/180)) sin((pi.*ang/180)); -sin((pi.*ang/180)) cos((pi.*ang/180))];
centerW = round(size(A,1)/2);
centerH = round(size(A,2)/2);
h=255.* uint8(ones(size(A)));
for x = 1:size(A,1)
for y = 1:size(A,2)
point =[x-centerW;y-centerH] ;
product = rotMat * point;
product = int16(product);
newx =product(1,1);
newy=product(2,1);
if newx+centerW<=size(A,1)&& newx+centerW > 0 && newy+centerH<=size(A,2)&& newy+centerH > 0
h(newx+centerW,newy+centerH) = A(x,y);
end
end
end