I'm using Python 2.7 and OpenCV 3.x for my project for omr sheet evaluation using web camera.
While finding the number of white pixels in around the center of circle,I came to know that the intensity values are wrong, but it shows the correct values in MATLAB when I'm using imtool('a1.png').
I'm using .png image (datatype uint8).
just run the code and in the image go to [360:370,162:172] coordinate and see the intensity values.. it should not be 0.
find the images here -> a1.png a2.png
Why is this happening?
import numpy as np
import cv2
from matplotlib import pyplot as plt
#select radius of circle
radius = 10;
#function for finding white pixels
def thresh_circle(img,ptx,pty):
centerX = ptx;
centerY = pty;
cntOfWhite = 0;
for i in range((centerX - radius),(centerX + radius)):
for j in range((centerY - radius), (centerY + radius)):
if(j < img.shape[0] and i < img.shape[1]):
val = img[i][j]
if (val == 255):
cntOfWhite = cntOfWhite + 1;
return cntOfWhite
MIN_MATCH_COUNT = 10
img1 = cv2.imread('a1.png',0) # queryImage
img2 = cv2.imread('a2.png',0) # trainImage
sift = cv2.SIFT()# Initiate SIFT detector
kp1, des1 = sift.detectAndCompute(img1,None)# find the keypoints and descriptors with SIFT
kp2, des2 = sift.detectAndCompute(img2,None)
FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
search_params = dict(checks = 50)
flann = cv2.FlannBasedMatcher(index_params, search_params)
matches = flann.knnMatch(des1,des2,k=2)
good = []# store all the good matches as per Lowe's ratio test.
for m,n in matches:
if m.distance < 0.7*n.distance:
good.append(m)
if len(good)>MIN_MATCH_COUNT:
src_pts = np.float32([ kp1[m.queryIdx].pt for m in good ]).reshape(-1,1,2)
dst_pts = np.float32([ kp2[m.trainIdx].pt for m in good ]).reshape(-1,1,2)
M, mask = cv2.findHomography(src_pts, dst_pts, cv2.LMEDS,5.0)
#print M
matchesMask = mask.ravel().tolist()
h,w = img1.shape
else:
print "Not enough matches are found - %d/%d" % (len(good),MIN_MATCH_COUNT)
matchesMask = None
img3 = cv2.warpPerspective(img1, M, (img2.shape[1],img2.shape[0]))
blur = cv2.GaussianBlur(img3,(5,5),0)
ret3,th3 = cv2.threshold(blur,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
ret,th2 = cv2.threshold(blur,ret3,255,cv2.THRESH_BINARY_INV)
print th2[360:370,162:172]#print a block of image
plt.imshow(th2, 'gray'),plt.show()
cv2.waitKey(0)
cv2.imwrite('th2.png',th2)
ptyc = np.array([170,200,230,260]);#y coordinates of circle center
ptxc = np.array([110,145,180,215,335,370,405,440])#x coordinates of circle center
pts_src = np.zeros(shape = (32,2),dtype=np.int);#x,y coordinates of circle center
ct = 0;
for i in range(0,4):
for j in range(0,8):
pts_src[ct][1] = ptyc[i];
pts_src[ct][0] = ptxc[j];
ct = ct+1;
boolval = np.zeros(shape=(8,4),dtype=np.bool)
ct = 0;
for j in range(0,8):
for i in range(0,4):
a1 = thresh_circle(th2,pts_src[ct][0],pts_src[ct][1])
ct = ct+1;
if(a1 > 50):
boolval[j][i] = 1
else:
boolval[j][i] = 0
Related
InfectionMatrix = zeros(100,100);
InfectionMatrix(50,50) = 1;
for k = 1:1:90
[i,j] = find(InfectionMatrix > 0.7);
%Random Number Generator
a = 0.0270;
b = 0.3250;
RANDOM = (b-a).*rand(8,1) + a;
%%%%%%%%%%%%%%%%%%%%%%%%
i(i == 1) = [];
i(i == length(InfectionMatrix)) = [];
j(j == 1) = [];
j(j == length(InfectionMatrix)) = [];
InfectionMatrix(i-1,j) = InfectionMatrix(i-1,j)+ RANDOM(1);
InfectionMatrix(i-1,j+1) = InfectionMatrix(i-1,j+1)+ RANDOM(2);
InfectionMatrix(i-1,j-1) = InfectionMatrix(i-1,j-1)+ RANDOM(3);
InfectionMatrix(i,j+1) = InfectionMatrix(i,j+1)+ RANDOM(4);
InfectionMatrix(i,j-1) = InfectionMatrix(i,j-1)+ RANDOM(5);
InfectionMatrix(i+1,j+1) = InfectionMatrix(i+1,j+1) + RANDOM(6);
InfectionMatrix(i+1,j-1) = InfectionMatrix(i+1,j-1) + RANDOM(7);
InfectionMatrix(i+1,j) = InfectionMatrix(i+1,j) + RANDOM(8);
rng('shuffle')
TooHigh = find(InfectionMatrix > 100);
for m = 1:1:length(TooHigh)
InfectionMatrix(TooHigh(m)) = 100;
end
end
h = heatmap(InfectionMatrix)
old_warning_state = warning('off', 'MATLAB:structOnObject');
hs = struct(h);
warning(old_warning_state);
hs.XAxis.TickValues = [];
hs.YAxis.TickValues = [];
I want to model kind of a simplistic view of a spreading infection. There are 2 things I'd like to accomplish.
Id like to know how to change the spread of the infection to be more circular, there are clearly issues with the corner nodes progressing in a star shape.
Id also like to know how to change the bottom half of the map to progress at half the rate of the top, i.e The Random number generation RANDOMwould be RANDOM/2
That kind of idea.
I'd appreciate any help to improve my code that is not relevant to the problems I specified also.
I'm not sure what you're aiming for but I think you would want to use a 2d convolution of the sort
Infected = zeros(100);
Infected(50,50) = 1;
InfectionMatrix = zeros(100);
for k = 1:90
RANDOM = (b-a).*rand(3,3) + a;
RANDOM(2,2) = 0;
RANDOM = RANDOM .* fspecial('gaussian',3,1); % sigma=1 3x3 kernel
InfectionMatrix = InfectionMatrix + conv2(Infected,RANDOM,'same');
Infected = InfectionMatrix > 0.7;
end
You can modulate the random number by a gaussian filter, like fspecial(), to ensure that they fall off at the corners.
I want to find the corners of objects.
I tried the following code:
Vstats = regionprops(BW2,'Centroid','MajorAxisLength','MinorAxisLength',...
'Orientation');
u = [Vstats.Centroid];
VcX = u(1:2:end);
VcY = u(2:2:end);
[VcY id] = sort(VcY); % sorting regions by vertical position
VcX = VcX(id);
Vstats = Vstats(id); % permute according sort
Bv = Bv(id);
Vori = [Vstats.Orientation];
VRmaj = [Vstats.MajorAxisLength]/2;
VRmin = [Vstats.MinorAxisLength]/2;
% find corners of vertebrae
figure,imshow(BW2)
hold on
% C = corner(VER);
% plot(C(:,1), C(:,2), 'or');
C = cell(size(Bv));
Anterior = zeros(2*length(C),2);
Posterior = zeros(2*length(C),2);
for i = 1:length(C) % for each region
cx = VcX(i); % centroid coordinates
cy = VcY(i);
bx = Bv{i}(:,2); % edge points coordinates
by = Bv{i}(:,1);
ux = bx-cx; % move to the origin
uy = by-cy;
[t, r] = cart2pol(ux,uy); % translate in polar coodinates
t = t - deg2rad(Vori(i)); % unrotate
for k = 1:4 % find corners (look each quadrant)
fi = t( (t>=(k-3)*pi/2) & (t<=(k-2)*pi/2) );
ri = r( (t>=(k-3)*pi/2) & (t<=(k-2)*pi/2) );
[rp, ip] = max(ri); % find farthest point
tc(k) = fi(ip); % save coordinates
rc(k) = rp;
end
[xc,yc] = pol2cart(tc+1*deg2rad(Vori(i)) ,rc); % de-rotate, translate in cartesian
C{i}(:,1) = xc + cx; % return to previous place
C{i}(:,2) = yc + cy;
plot(C{i}([1,4],1),C{i}([1,4],2),'or',C{i}([2,3],1),C{i}([2,3],2),'og')
% save coordinates :
Anterior([2*i-1,2*i],:) = [C{i}([1,4],1), C{i}([1,4],2)];
Posterior([2*i-1,2*i],:) = [C{i}([2,3],1), C{i}([2,3],2)];
end
My input image is :
I got the following output image
The bottommost object in the image is not detected properly. How can I correct the code? It fails to work for a rotated image.
You can get all the points from the image, and use kmeans clustering and partition the points into 8 groups. Once partition is done, you have the points in and and you can pick what ever the points you want.
rgbImage = imread('your image') ;
%% crop out the unwanted white background from the image
grayImage = min(rgbImage, [], 3);
binaryImage = grayImage < 200;
binaryImage = bwareafilt(binaryImage, 1);
[rows, columns] = find(binaryImage);
row1 = min(rows);
row2 = max(rows);
col1 = min(columns);
col2 = max(columns);
% Crop
croppedImage = rgbImage(row1:row2, col1:col2, :);
I = rgb2gray(croppedImage) ;
%% Get the white regions
[y,x,val] = find(I) ;
%5 use kmeans clustering
[idx,C] = kmeans([x,y],8) ;
%%
figure
imshow(I) ;
hold on
for i = 1:8
xi = x(idx==i) ; yi = y(idx==i) ;
id1=convhull(xi,yi) ;
coor = [xi(id1) yi(id1)] ;
[id,c] = kmeans(coor,4) ;
plot(coor(:,1),coor(:,2),'r','linewidth',3) ;
plot(c(:,1),c(:,2),'*b')
end
Now we are able to capture the regions..the boundary/convex hull points are in hand. You can do what ever math you want with the points.
Did you solve the problem? I Looked into it and it seems that the rotation given by 'regionprops' seems to be off. To fix that I've prepared a quick solution: I've dilated the image to close the gaps, found 4 most distant peaks of each spine, and then validated if a peak is on the left, or on the right of the centerline (that I have obtained by extrapolating form sorted centroids). This method seems to work for this particular problem.
BW2 = rgb2gray(Image);
BW2 = imbinarize(BW2);
%dilate and erode will help to remove extra features of the vertebra
se = strel('disk',4,4);
BW2_dilate = imdilate(BW2,se);
BW2_erode = imerode(BW2_dilate,se);
sb = bwboundaries(BW2_erode);
figure
imshow(BW2)
hold on
centerLine = [];
corners = [];
for bone = 1:length(sb)
x0 = sb{bone}(:,2) - mean(sb{bone}(:,2));
y0 = sb{bone}(:,1) - mean(sb{bone}(:,1));
%save the position of the centroid
centerLine = [centerLine; [mean(sb{bone}(:,1)) mean(sb{bone}(:,2))]];
[th0,rho0] = cart2pol(x0,y0);
%make sure that the indexing starts at the dip, not at the corner
lowest_val = find(rho0==min(rho0));
rho1 = [rho0(lowest_val:end); rho0(1:lowest_val-1)];
th00 = [th0(lowest_val:end); th0(1:lowest_val-1)];
y1 = [y0(lowest_val:end); y0(1:lowest_val-1)];
x1 = [x0(lowest_val:end); x0(1:lowest_val-1)];
%detect corners, using smooth data to remove noise
[pks,locs] = findpeaks(smooth(rho1));
[pksS,idS] = sort(pks,'descend');
%4 most pronounced peaks are where the corners are
edgesFndCx = x1(locs(idS(1:4)));
edgesFndCy = y1(locs(idS(1:4)));
edgesFndCx = edgesFndCx + mean(sb{bone}(:,2));
edgesFndCy = edgesFndCy + mean(sb{bone}(:,1));
corners{bone} = [edgesFndCy edgesFndCx];
end
[~,idCL] = sort(centerLine(:,1),'descend');
centerLine = centerLine(idCL,:);
%extrapolate the spine centerline
yDatExt= 1:size(BW2_erode,1);
extrpLine = interp1(centerLine(:,1),centerLine(:,2),yDatExt,'spline','extrap');
plot(centerLine(:,2),centerLine(:,1),'r')
plot(extrpLine,yDatExt,'r')
%find edges to the left, and to the right of the centerline
for bone = 1:length(corners)
x0 = corners{bone}(:,2);
y0 = corners{bone}(:,1);
for crn = 1:4
xCompare = extrpLine(y0(crn));
if x0(crn) < xCompare
plot(x0(crn),y0(crn),'go','LineWidth',2)
else
plot(x0(crn),y0(crn),'ro','LineWidth',2)
end
end
end
Solution
I have images of rectangles or deformed rectangles with rounded corners, like this:
or this:
is there a way to make the corners squared with matlab?
And then how can i get the coordinates of those new corners?
Thank you
Explanation
This problem is similar to the following question. My answer will be somehow similar to my answer there, with the relevant modifications.
we want to find the parallelogram corners which fits the most to the given shape.
The solution can be found by optimization, as follows:
find an initial guess for the 4 corners of the shape. This can be done by finding the boundary points with the highest curvature, and use kmean clustering to cluster them into 4 groups.
create a parallelogram given these 4 corners, by drawing a line between each pair of corresponding corners.
find the corners which optimize the Jaccard coefficient of the boundary image and the generated parallelogram map.
The optimization will done locally on each corner, in order to spare time.
Results
Initial corner guess (corners are marked in blue)
final results:
Code
main script
%reads image and binarize it
I = rgb2gray(imread('eA4ci.jpg')) > 50;
%finds boundry of largerst connected component
boundries = bwboundaries(I,8);
numPixels = cellfun(#length,boundries);
[~,idx] = max(numPixels);
B = boundries{idx};
%finds best 4 corners
[ corners ] = optimizeCorners(B);
%generate line mask given these corners, fills the result
linesMask = drawLines(size(I),corners,corners([2:4,1],:));
rectMask = imfill(linesMask,'holes');
%remove biggest CC from image, adds linesMask instead
CC = bwconncomp(I,8);
numPixels = cellfun(#numel,CC.PixelIdxList);
[~,idx] = max(numPixels);
res = I;
res(CC.PixelIdxList{idx}) = 0;
res = res | rectMask;
optimize corners function:
function [ corners] = optimizeCorners(xy)
%finds the corners which fits the most for this set of points
Y = xy(:,1);
X = xy(:,2);
%initial corners guess
corners = getInitialCornersGuess(xy);
boundriesIm = zeros(max(Y)+20,max(X)+20);
boundriesIm(sub2ind(size(boundriesIm),xy(:,1),xy(:,2))) = 1;
%R represents the search radius
R = 7;
%continue optimizing as long as there is no change in the final result
unchangedIterations = 0;
while unchangedIterations<4
for ii=1:4
%optimize corner ii
currentCorner = corners(ii,:);
bestCorner = currentCorner;
bestRes = calcEnergy(boundriesIm,corners);
cornersToEvaluate = corners;
for yy=currentCorner(1)-R:currentCorner(1)+R
for xx=currentCorner(2)-R:currentCorner(2)+R
cornersToEvaluate(ii,:) = [yy,xx];
res = calcEnergy(boundriesIm,cornersToEvaluate);
if res > bestRes
bestRes = res;
bestCorner = [yy,xx];
end
end
end
if isequal(bestCorner,currentCorner)
unchangedIterations = unchangedIterations + 1;
else
unchangedIterations = 0;
corners(ii,:) = bestCorner;
end
end
end
end
function res = calcEnergy(boundriesIm,corners)
%calculates the score of the corners list, given the boundries image.
%the result is acutally the jaccard index of the boundries map and the
%lines map
linesMask = drawLines(size(boundriesIm),corners,corners([2:4,1],:));
res = sum(sum(linesMask&boundriesIm)) / sum(sum(linesMask|boundriesIm));
end
get initial corners function:
function corners = getInitialCornersGuess(boundryPnts)
%calculates an initial guess for the 4 corners
%finds corners by performing kmeans on largest curvature pixels
[curvatureArr] = calcCurvature(boundryPnts, 5);
highCurv = boundryPnts(curvatureArr>0.3,:);
[~,C] = kmeans([highCurv(:,1),highCurv(:,2)],4);
%sorts the corners from top to bottom - preprocessing stage
C = int16(C);
corners = zeros(size(C));
%top left corners
topLeftInd = find(sum(C,2)==min(sum(C,2)));
corners(1,:) = C(topLeftInd,:);
%bottom right corners
bottomRightInd = find(sum(C,2)==max(sum(C,2)));
corners(3,:) = C(bottomRightInd,:);
%top right and bottom left corners
C([topLeftInd,bottomRightInd],:) = [];
topRightInd = find(C(:,2)==max(C(:,2)));
corners(4,:) = C(topRightInd,:);
bottomLeftInd = find(C(:,2)==min(C(:,2)));
corners(2,:) = C(bottomLeftInd,:);
end
function [curvatureArr] = calcCurvature(xy, halfWinSize)
%calculate the curvature of a list of points (xy) given a window size
%curvature calculation
curvatureArr = zeros(size(xy,1),1);
for t=1:halfWinSize
y = xy(t:halfWinSize:end,1);
x = xy(t:halfWinSize:end,2);
dx = gradient(x);
ddx = gradient(dx);
dy = gradient(y);
ddy = gradient(dy);
num = abs(dx .* ddy - ddx .* dy) + 0.000001;
denom = dx .* dx + dy .* dy + 0.000001;
denom = sqrt(denom);
denom = denom .* denom .* denom;
curvature = num ./ denom;
%normalizing
if(max(curvature) > 0)
curvature = curvature / max(curvature);
end
curvatureArr(t:halfWinSize:end) = curvature;
end
end
draw lines function:
function mask = drawLines(imgSize, P1, P2)
%generates a mask with lines, determine by P1 and P2 points
mask = zeros(imgSize);
P1 = double(P1);
P2 = double(P2);
for ii=1:size(P1,1)
x1 = P1(ii,2); y1 = P1(ii,1);
x2 = P2(ii,2); y2 = P2(ii,1);
% Distance (in pixels) between the two endpoints
nPoints = ceil(sqrt((x2 - x1).^2 + (y2 - y1).^2));
% Determine x and y locations along the line
xvalues = round(linspace(x1, x2, nPoints));
yvalues = round(linspace(y1, y2, nPoints));
% Replace the relevant values within the mask
mask(sub2ind(size(mask), yvalues, xvalues)) = 1;
end
I'm writing the code in Matlab to find interest point using DoG in the image.
Here is the main.m:
imTest1 = rgb2gray(imread('1.jpg'));
imTest1 = double(imTest1);
sigma = 0.6;
k = 5;
thresh = 3;
[x1,y1,r1] = DoG(k,sigma,thresh,imTest1);
%get the interest points and show it on the image with its scale
figure(1);
imshow(imTest1,[]), hold on, scatter(y1,x1,r1,'r');
And the function DoG is:
function [x,y,r] = DoG(k,sigma,thresh,imTest)
x = []; y = []; r = [];
%suppose 5 levels of gaussian blur
for i = 1:k
g{i} = fspecial('gaussian',size(imTest),i*sigma);
end
%so 4 levels of DoG
for i = 1:k-1
d{i} = imfilter(imTest,g{i+1}-g{i});
end
%compare the current pixel in the image to the surrounding pixels (26 points),if it is the maxima/minima, this pixel will be a interest point
for i = 2:k-2
for m = 2:size(imTest,1)-1
for n = 2:size(imTest,2)-1
id = 1;
compare = zeros(1,27);
for ii = i-1:i+1
for mm = m-1:m+1
for nn = n-1:n+1
compare(id) = d{ii}(mm,nn);
id = id+1;
end
end
end
compare_max = max(compare);
compare_min = min(compare);
if (compare_max == d{i}(m,n) || compare_min == d{i}(m,n))
if (compare_min < -thresh || compare_max > thresh)
x = [x;m];
y = [y;n];
r = [r;abs(d{i}(m,n))];
end
end
end
end
end
end
So there's a gaussian function and the sigma i set is 0.6. After running the code, I find the position is not correct and the scales looks almost the same for all interest points. I think my code should work but actually the result is not. Anybody know what's the problem?
I have to draw a hipsometric map on a 3D plot. I have two vectors 1x401 (named xLabels and yLabels) which are the geo coordinates, and401x401(namedA`) matrix with the altitude data. To plot the data I use:
surf(xLabels, yLabels,A,'EdgeColor','None','Marker','.');
which leads to something like that:
But i would like to have something like that:
On the second image, only the surface is plotted, while my image looks like pillars.
I tried even make my vectors to 401x401 using meshgrid but it did not have any effect.
Do you have any idea what I should change?
#EDIT
I checked for X and Y data. I quess is too small interval (0.0083), but when i try plot good second of upper plots with same interval it draws correctly.
#EDIT2:
sizeX = 4800;
sizeY = 6000;
pixdegree = 0.0083; % 1 pixel is 0.0083 degree on map
intSize = 2;
lon = 37 + (35/60);
lat = 55+ (45/60);
fDEM = 'E020N90';
fHDR = 'E020N90.HDR';
[startXY, endXY] = calcFirstPixel(lon, lat); %calc borders for my area
f = fopen('E020N90.DEM');
offset = (startXY(1,2)*sizeX*intSize)+(startXY(1,1)*intSize);
fseek(f, offset,0); %seek from curr file pos
x = 0;
A = [];
BB = [];
jump = (intSize*sizeX)-(401*2);
while x<401
row = fread(f, 802);
fseek(f, jump, 0); %jump 2 next row
A = [A row];
x = x+1;
end
fclose(f);
A = A';
A = A(:,2:2:802);
m1 = min(A(:)); %wartość minimalna dla naszej podziałki
m2 = max(A(:)); %wartość maksymalna dla naszej podziałki
step = m2/8; % będzie 8 kolorów
highScale = m1:step:m2-step; %wartości graniczne dla każdego z nich
%handles.axes1 = A;
colormap(hObject, jet(8));
startXtick = 20 + pixdegree*startXY(1,1);
endXtick = 20 + pixdegree*endXY(1,1);
startYtick = 90 - pixdegree*endXY(1,2);
endYtick = 90 - pixdegree*startXY(1,2);
[XX,YY] = ndgrid(startXtick:pixdegree:endXtick,startYtick:pixdegree:endYtick);
xLabels = startXtick:pixdegree:endXtick;
yLabels = startYtick:pixdegree:endYtick;
surf(xLabels, yLabels,A,'EdgeColor','None','Marker','.');
set(gca,'YDir','normal');
grid on;
view([45 45])
And .DEM files
function [startXY, endXY] = calcFirstPixel(lon,lat)
global fHDR;
format = '%s %s';
f = fopen(fHDR);
cont = textscan(f, format);
LonStart = str2double(cont{1,2}{11,1});
LatStart = str2double(cont{1,2}{12,1});
diffPerPix = str2double(cont{1,2}{13,1});
fclose(f);
x = LonStart;
countX = 0
y = LatStart;
countY= 0;
while x<lon
x=x+diffPerPix
countX = countX +1;
end
while y>lat
y=y-diffPerPix
countY = countY+1;
end
startXY= [countX-200 countY-200];
endXY = [countX+200 countY+200];
end