How to draw a rectangle using 4 corners on an image in Matlab R2018b? - matlab

In Matlab, there is rectangle('Position',[x,y,w,h]) to draw a rectangle object, that w and h are a width and a height respectively (This link). While I try to draw a rectangle on an image using 4 corners: min_x, max_x, min_y and max_y that are specified in the following image.
Ex:
min_x = 193; max_x = 220; min_y = 168; max_y = 190;
I saw this link and like that, but they couldn't help me. Is there any way to draw a rectangle with 4 corners?

A = imresize( imread('peppers.png'),0.6);%resizing for better visibility
min_x = 193; max_x = 220; min_y = 168; max_y = 190;
x = min_x;
y = min_y;
w = max_x-min_x;
h = max_y-min_y;
imshow(A)
rectangle('Position',[x,y,w,h],'EdgeColor','r','Linewidth',3);
% Or insert shape to bitmap:
% B = insertShape(A,'rectangle',[x,y,w,h]);
% imshow(B)

Related

Calculate objects circumscribed radius and inscribed radius - Matlab

I am trying to calculate two objects circumscribed radius and inscribed radius using the code below. I used for the inscribedRadius parameter from this script and for the circumscribed radius I used this function
I do not understand why I get for the box shape that the inscribed radius is bigger than the circumscribed radius. Any idea what is wrong? And how to fix it?
Image
Code:
clc;
clear;
RGB = imcomplement(imread('https://i.stack.imgur.com/8WLAt.jpg'));
I = rgb2gray(RGB);
bw = imbinarize(I);
bw = imfill(bw,'holes');
imshow(bw)
hold on;
[B,L] = bwboundaries(bw,'noholes');
stats = regionprops(L,'Centroid','MajorAxisLength');
for i = 1 : numel(stats)
b = B{i};
c = stats(i).Centroid;
y = b(:,1);
x = b(:,2);
plot( b(:,2),b(:,1),'Color','red','linewidth',2);
text(c(1),c(2),num2str(i),'Color','red');
xMin = min(x);
xMax = max(x);
yMin = min(y);
yMax = max(y);
scalingFactor = 1000 / min([xMax-xMin, yMax-yMin]);
x2s = (x - xMin) * scalingFactor + 1;
y2s = (y - yMin) * scalingFactor + 1;
mask = poly2mask(x2s, y2s, ceil(max(y2s)), ceil(max(x2s)));
edtImage = bwdist(~mask);
inscribedRadius = max(edtImage(:));
[yCenter, xCenter] = find(edtImage == inscribedRadius);
xCenter = (xCenter - 1)/ scalingFactor + xMin;
yCenter = (yCenter - 1)/ scalingFactor + yMin;
inscribedRadius = inscribedRadius / scalingFactor
[circumscribedCenter,circumscribedRadius] = minboundcircle(x,y); % from https://www.mathworks.com/matlabcentral/fileexchange/34767-a-suite-of-minimal-bounding-objects?focused=3820656&tab=function
circumscribedRadius
end
The results are:
Object 1: inscribedRadius = 264, cumscribedRadius = 186.6762
Object 2: inscribedRadius = 130.4079, circumscribedRadius = 132.3831
The values of object 1 (box) are wrong as the inscribedRadius can not be bigger than the cumscribedRadius. They are fine for object 2 (circle)
If you look at the mask image, you'll notice that the square shape is drawn touching the right and bottom edges of the image. There's background only along the left and top of the shape. The distance transform bwdist(~mask) subsequently computes the distance to the background for each pixel within the shape, but since there's background only to the left and top, the pixel at the bottom right of the shape has a distance of 1000, rather than 1. The distance transform is supposed to have a maximum in the middle, at a point equidistant to at least the three nearest shape edge points.
The solution is simple: poly2mask must create an image that is one pixel wider and taller:
mask = poly2mask(x2s, y2s, ceil(max(y2s)) + 1, ceil(max(x2s)) + 1);
^^^ ^^^
With this change, the computed inscribedRadius for the square is 132, as expected.

how can I Rotate the image around the center using transformPointsForward and Getting the coordinates of the four corners of the changed image؟

I want to rotate the image arround the center.I usesd transformPointForward function for do this.I want to getting the coordinate of the four corners of the changed image.in below you can see my code.thanks for your help.
theta=+50;
tform = affine2d([cosd(theta) -sind(theta) 0;sind(theta) cosd(theta) 0; 0 0
1]);
A = imread('pout.tif');
corners = [1,1;1,size(A,2);size(A,1),1;size(A,1),size(A,2)];
X = transformPointsForward(tform,corners);
Rin = imref2d(size(A))
Rin.XWorldLimits = Rin.XWorldLimits-mean(Rin.XWorldLimits);
Rin.YWorldLimits = Rin.YWorldLimits-mean(Rin.YWorldLimits);
[out,ref] = imwarp(A,Rin,tform);
figure,
subplot(1,2,1),imshow(A,[])
subplot(1,2,2),imshow(out,[])
X(:,1) = X(:,1) - ref.XWorldLimits(1);
X(:,2) = X(:,2) - ref.YWorldLimits(1);

Why does the figure size change when I use print -dpng and -djpeg?

I have this code:
x = 1:1:1000;
Hw = 2;
T1 = 60;
L1 = 100;
eta1 = (Hw/2)*(sin(2*pi*((x/L1)-(1/T1))));
units_out ='centimeters';
width = 8;
height = 6;
typefon = 'Times';
fsize_axis = 8;
fsize_label = 10;
fig1 = figure;
h0 = plot(x, eta1,'r');
ylim([-2 2]);
set(gca,'FontName',typefon,'FontSize',fsize_axis,'FontWeight','bold');
title('Water wave 1');
xl0 = xlabel('x (m)');
set(xl0,'FontSize',fsize_label);
yl0 =ylabel('\eta (m)');
set(yl0,'FontSize',fsize_label);
pos =get(gcf,'Position');
pos(3) = width;
pos(4) = height;
set(gcf,'units','centimeters','Position',pos);
set(gca,'LooseInset',max(get(gca,'TightInset'), 0.02))
set(gcf,'PaperPositionMode','auto');
print('my_figure', '-dpng', '-r600');
delete(fig1);
winopen('my_figure.png');
I got an image of: 8.0 x 6.0 cm; 3.15 x 2.36 inches (I expected this size), but if I only modify the formattype to –djpeg of print function, I got a graphics file of: 66.7 x 50.0 cm; 26.25 x 19.68 inches. Why does the size change? How can I compute the size of the image, in centimeters, taking into account the resolution of the image?

How to square the corners of a "rectangle" in a bw image with matlab

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

How to place an image A onto image B BUT I WANT TO IGNORE all O pixels of image A

I want to place a modelImage (RGB image) on baseImage (RGB image) where the center of modelImage will be placed at pPoint.
I already wrote the function.
And it works. However, there are some 0 pixels in the modelImage. I do not want to place 0 pixels of modelImage onto baseImage. Can you help me to modify my function?
% Put the modelImage onto baseImage at pPoint
function newImage = imgTranslate(modelImage,baseImage, pPoint)
[nRow nCol noDim] = size(modelImage);
pPointX = pPoint(1);
pPointY = pPoint(2);
startColumn = pPointY - nCol/2;
startRow = pPointX - nRow/2;
startColumn = round(startColumn);
startRow = round(startRow);
endColumn = startColumn+ nCol;
endRow = startRow+nRow;
%% Place modelImage onto baseImage BUT I WANT TO IGNORE O pixels of modelImage
baseImage(startRow:(endRow-1),startColumn:(endColumn-1),:) = modelImage;
newImage = baseImage;
Using FOR and IF works but it will slow the progam
%%
for i = startRow: (endRow-1)
x = (i-startRow +1);
for j = startColumn : (endColumn-1)
y = j-startColumn + 1;
if modelImage(x,y,:)~=0
baseImage(i,j,:) = modelImage(x,y,:);
end
end
end
Any way to not to use FOR and IF ?
There may be a way to simplify this, but something like (untested):
% Indicator map of non-zeros
nzs = any(modelImage,3);
nzs = repmat(nzs, [1 1 3]);
% Crop destination image
tmpImage = baseImage(startRow:(endRow-1),startColumn:(endColumn-1),:);
% Replace all but non-zeros
tmpImage(nzs) = modelImage(nzs);
% Place into output image as before
baseImage(startRow:(endRow-1),startColumn:(endColumn-1),:) = tmpImage;
% Indicator map of non-zeros
zs = modelImage(:,:,:)==0;
nzs = ~zs;
% Crop destination image
tmpImage = baseImage(startRow:(endRow-1),startColumn:(endColumn-1),:);
% Replace all but non-zeros
tmpImage(nzs) = modelImage(nzs);
% Place into output image as before
baseImage(startRow:(endRow-1),startColumn:(endColumn-1),:) = tmpImage;