I'm trying to plot rectangles around blobs in every frame of a video. Method insertShape works but not very well. Method rectangle doesn't seem to do anything and I don't understand where's the problem as it works with a .avi file but won't with .mp4 ...
firstRunFlag = true;
threshold = 0.18;
se_erode = strel('square', 3);
se_dilate = strel('square', 30);
v = VideoReader('Traffic.mp4');
figure;
while hasFrame(v)
frame_now = readFrame(v);
if (firstRunFlag)
frame_prev = frame_now;
firstRunFlag = false;
end
frame_diff = frame_now - frame_prev;
frame_diff_grayscale = rgb2gray(frame_diff);
bw = im2bw(frame_diff_grayscale, threshold);
bw = imerode(bw, se_erode);
bw = imdilate(bw, se_dilate);
bw = imfill(bw,'holes');
boxes = regionprops(bw, 'BoundingBox');
imshow(frame_now);
for i=1:length(boxes)
this_box = boxes(i).BoundingBox;
rectangle('Position', [this_box(1), this_box(2), this_box(3), this_box(4)], 'EdgeColor', 'r', 'LineWidth', 2)
end
frame_prev = frame_now;
end
It also seems to be working on a single image, but not when displaying frame after frame...
Sometimes matlab does not update a plot, when there are several operations applied to it (like imshowing consecutive frames and rectanlges). Thus, it is useful to force matlab to update the plot using drawnow command.
Related
I am a little bit new to matlab and imageprocessing and I was given a task at my faculty to carry out a project which detects the lanes for a moving car in a video. I tried to use some tutorials on Mathworks and other sites and there were really helpful and I came out with a code that detects lanes in an image and I just want to know how to apply my code on a video as I see it working properly on an image.
and here is my code :
img = imread ('test_image.jpg');
I = rgb2gray (img);
%making a gaussian kernel
sigma = 1 ; %standard deviation of distribution
kernel = zeros (5,5); %for a 5x5 kernel
W = 0 ;
for i = 1:5
for j = 1:5
sq_dist = (i-3)^2 + (j-3)^2 ;
kernel (i,j) = exp (-1*exp(sq_dist)/(2*sigma));
W = W + kernel (i,j) ;
end
end
kernenl = kernel/W ;
%Now we apply the filter to the image
[m,n] = size (I) ;
output = zeros (m,n);
Im = padarray (I , [2 2]);
for i=1:m
for j=1:n
temp = Im (i:i+4 , j:j+4);
temp = double(temp);
conv = temp.*kernel;
output(i,j) = sum(conv(:));
end
end
output = uint8(output);
%--------------Binary image-------------
level = graythresh(output);
c= im2bw (output,level);
%---------------------------------------
output2 = edge (c , 'canny',level);
figure (1);
%Segment out the region of interest
ROI = maskedImage;
CannyROI = edge (ROI , 'canny',.45);
%----------------------------------
set (gcf, 'Position', get (0,'Screensize'));
%subplot (141), imshow (I), title ('original image');
%subplot (142), imshow (c), title ('Binary image');
%subplot (143), imshow (output2), title ('Canny image');
%subplot (144), imshow (CannyROI), title ('ROI image');
[H ,T ,R] = hough(CannyROI);
imshow (H,[],'XData',T,'YData',R,'initialMagnification','fit');
xlabel('\theta'), ylabel('\rho');
axis on , axis normal, hold on ;
P = houghpeaks(H,5,'threshold',ceil (0.3*max(H(:))));
x = T(P(:,2));
y = R(P(:,1));
plot (x,y,'s','color','white');
%Find lines and plot them
lines = houghlines (CannyROI,T,R,P,'FillGap',5,'MinLength',7);
figure, imshow (img), hold on
max_len = 0 ;
for k = 1:length(lines);
xy = [lines(k).point1; lines(k).point2];
plot (xy(:,1), xy(:,2), 'LineWidth', 5 , 'Color', 'blue');
%plot beginnings and ends of the lines
plot (xy(1,1), xy(1,2),'x', 'LineWidth', 2, 'Color', 'yellow');
plot (xy(2,1), xy(2,2),'x', 'LineWidth', 2, 'Color', 'red');
%determine the endpoints of the longest line segment
len = norm(lines(k).point1 - lines(k).point2);
if (len>max_len)
max_len = len;
xy_long = xy;
end
end
and here is the link of the image and the video :
https://github.com/rslim087a/road-video
https://github.com/rslim087a/road-image
Thanks in advance.
Basically video processing happens in such a way that video will be converted to video frames (images). So if you need, you can convert your video to video frames and run the code, looping over the folder having the video frames. Change the imread function to get images from video frames folder...
img = imread(path_to_video_frames_folder/*)
Given two coordinate points A and B and its gradient 'slopes'. Now, I want to draw a line (with linspace - function) on an image which worked for lines with a gradient ~1. The line stopped at the image boundary (due to xlims and ylims).
imshow(I)
xlims = xlim(gca);
ylims = ylim(gca);
Now the problem: I try to repeat for another line which is nearly vertical and it did not stop at the image boundary (see picture):
Any solutions how I can draw a line using a y=mx+c equation that stops at the image boundary independent from the gradient?
EDIT:
img = uint8(zeros(382, 382));
pointA = [181.4594, 129.7092];
pointB = [185.3411, 251.6005];
imshow(img)
hold on
plot(pointA(1), pointA(2), 'ro')
plot(pointB(1), pointB(2), 'bo')
hold off
% From y = mx + x
slope = 31.4015;
intercept = -5.5684e+03;
xlims = xlim(gca);
ylims = ylim(gca);
y = xlims*slope + intercept;
Xline = linspace(xlims(1), xlims(2), 382);
Xline_pole1 = linspace(xlims(1), pointA(1), 382/2);
Xline_pole2 = linspace(xlims(2), pointB(1), 382/2);
Yline = Xline*slope + intercept;
Yline_pole1 = Xline_pole1*slope + intercept;
Yline_pole2 = Xline_pole2*slope + intercept;
hold on
plot( Xline_pole1, Yline_pole1, 'Color', 'b', 'LineWidth', 3 );
hold off
% Check how many coordinates are within image frame
for zz=1:length(Xline_pole1)
hold on
plot(Xline_pole1(zz),Yline_pole1(zz), 'm+');
end
Easy workaround:
Just reset your limits after you plotted your lines
imshow(I)
xlims = xlim(gca);
ylims = ylim(gca);
% plot your lines
xlim(xlims)
ylim(ylims)
I'm detecting circles from an image using imfindcircles function.
Below is the code.
image here
img= imread('image.png');
imshow(img);
rmin=10
rmax=50
[centersDarkl, radiiDarkl]=imfindcircles(img,
[rmin,rmax],'ObjectPolarity','dark','Sensitivity',0.80);
viscircles(centersDarkl, radiiDarkl,'LineStyle','--')
Now, I want to crop the detected circles and save them as different figures.
Here is a solution that works for this image. I used floor and ceil to avoid the edges and rmax had to be larger than 75.
[img,map] = imread('MwBQo.png','png');
img = ind2rgb(img, map);
figure;
imshow(img);
rmin = 10;
rmax = 80;
[centersDarkl, radiiDarkl] = imfindcircles(img,...
[rmin,rmax],'ObjectPolarity','dark','Sensitivity',0.80);
viscircles(centersDarkl, radiiDarkl,'LineStyle','--')
for iCirc = 1:size(centersDarkl,1)
cropped{iCirc,1} = img(...
ceil(centersDarkl(iCirc,2)-radiiDarkl(iCirc)):...
floor(centersDarkl(iCirc,2)+radiiDarkl(iCirc)),...
ceil(centersDarkl(iCirc,1)-radiiDarkl(iCirc)):...
floor(centersDarkl(iCirc,1)+radiiDarkl(iCirc)),:);
end
figure;
subplot(1,2,1)
imshow(cropped{1})
subplot(1,2,2)
imshow(cropped{2})
I have the input image. I want to create the boundary around the object and marked the boundary pixels as gray i.e. 128 intensity value. I need this type of output image. I traced the boundary of the object:
level = graythresh(im);
BW = im2bw(im,level);
figure; imshow(BW);
[B,L] = bwboundaries(BW,'noholes');
imshow(im);
hold on
for k = 1:length(B)
boundary = B{k};
plot(boundary(:,2), boundary(:,1), 'Color', [0.5 0.5 0.5], 'LineWidth', 5)
end
But it will only plot the boundary over the image. I want to create this boundary around the object of input image. How can I do this? I hope my question is clear.
While I don't know why you wan this, a word of advice: you may not want to do it. You are losing information of the image by doing so. It is possible that for you application knowing the indices of the boundaries is enough, and you do already know them.
However, this is what you would need to do in case of really wanting to do it:
clear;
clc;
im=imread('https://i.stack.imgur.com/r7uQz.jpg');
im=im(31:677,90:1118);
level = graythresh(im);
BW = im2bw(im,level);
[B,L] = bwboundaries(BW,'noholes');
for k = 1:length(B)
boundary = B{k};
%%%%%%%%% Fill the boundary locations with he desired value.
for ii=1:size(boundary,1)
im(boundary(ii,1), boundary(ii,2))=128;
end
end
If you want "fat" lines as in your image, add this after:
im128=im==128;
bigboundary=imdilate(im128,ones(5));
im(bigboundary)=128;
You can binarize the image and detect the contours using OpenCV.
Here is the Python implementation:
img = cv2.imread(r'D:\Image\temp1.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret,bw = cv2.threshold(gray,100,255,cv2.THRESH_BINARY)
_,contours,hierarchy = cv2.findContours(bw, cv2.RETR_CCOMP, 1)
for cnt in contours:
c = np.random.randint(0,256,3)
c = (int(c[0]), int(c[1]), int(c[2]))
cv2.drawContours(img,[cnt],0,c,2)
Output image:
After finding boundaries of my regions of interest in an RGB image I want to fill them with specific color on the original picture
img=imread('I.png');
BW=~im2bw(img,0.5);
B = bwboundaries(a2);
for k = 1:length(B)
boundary = B{k};
% here should color everything inside boundary in blue
end
What function can I use to do this? I tried also using imshow() and than ploting regions on it, but don't know how to save it in the original resolution.
If you insist on filling with polygon, you can use fill, but then you might face some problems:
img = imread('Prueba.jpg');
figure;
imshow(img)
BW = ~im2bw(img, 0.55);
B = bwboundaries(BW);
hold on
for k = 1:length(B)
boundary = B{k};
fill(boundary(:, 2), boundary(:, 1), 'b')
end
As shown in this example, there are regions of the image that are surrounded by a boundary but they are actually supposed to be outside the boundary.
Instead, in this way you can avoid the issue:
imgR = img(:, :, 1);
imgG = img(:, :, 2);
imgB = img(:, :, 3);
imgR(BW) = 0;
imgG(BW) = 0;
imgB(BW) = intmax(class(imgB));
IMG = cat(3, imgR, imgG, imgB);
figure; imshow(IMG)