Related
I have an image and I would like to blur it in one specific direction and distance using Matlab.
I found out there is a filter called fspecial('motion',len,theta).
Here there is an example:
I = imread('cameraman.tif');
imshow(I);
H = fspecial('motion',20,45);
MotionBlur = imfilter(I,H,'replicate');
imshow(MotionBlur);
However the blurred picture is blurred in 2 directions! In this case 225 and 45 degrees.
What should it do in order to blur it just in a specific direction (e.g. 45) and not both?
I think you want what's called a "comet" kernel. I'm not sure what kernel is used for the "motion" blur, but I'd guess that it's symmetrical based on the image you provided.
Here is some code to play with that applies the comet kernel in one direction. You'll have to change things around if you want an arbitrary angle. You can see from the output that it's smearing in one direction, since there is a black band on only one side (due to the lack of pixels there).
L = 5; % kernel width
sigma=0.2; % kernel smoothness
I = imread('cameraman.tif');
x = -L:1.0:L;
[X,Y] = meshgrid(x,x);
H1 = exp((-sigma.*X.^2)+(-sigma.*Y.^2));
kernel = H1/sum((H1(:)));
Hflag = double((X>0));
comet_kernel = Hflag.*H1;
comet_kernel=comet_kernel/sum(comet_kernel(:));
smearedImage = conv2(double(I),comet_kernel,'same');
imshow(smearedImage,[]);
Updated code: This will apply an arbitrary rotation to the comet kernel. Note also the difference between sigma in the previous example and sx and sy here, which control the length and width parameters of the kernel, as suggested by Andras in the comments.
L = 5; % kernel width
sx=3;
sy=10;
theta=0;
I = imread('cameraman.tif');
x = -L:1.0:L;
[X,Y] = meshgrid(x,x);
rX = X.*cos(theta)-Y.*sin(theta);
rY = X.*sin(theta)+Y.*cos(theta);
H1 = exp(-((rX./sx).^2)-((rY./sy).^2));
Hflag = double((0.*rX+rY)>0);
H1 = H1.*Hflag;
comet_kernel = H1/sum((H1(:)))
smearedImage = conv2(double(I),comet_kernel,'same');
imshow(smearedImage,[]);
Based on Anger Density's answer I wrote this code that solves my problem completely:
L = 10; % kernel width
sx=0.1;
sy=100;
THETA = ([0,45,90,135,180,225,270,320,360])*pi/180;
for i=1:length(THETA)
theta=(THETA(i)+pi)*-1;
I = imread('cameraman.tif');
x = -L:1.0:L;
[X,Y] = meshgrid(x,x);
rX = X.*cos(theta)-Y.*sin(theta);
rY = X.*sin(theta)+Y.*cos(theta);
H1 = exp(-((rX./sx).^2)-((rY./sy).^2));
Hflag = double((0.*rX+rY)>0);
H1 = H1.*Hflag;
comet_kernel = H1/sum((H1(:)));
smearedImage = conv2(double(I),comet_kernel,'same');
% Fix edges
smearedImage(:,[1:L, end-L:end]) = I(:,[1:L, end-L:end]); % Left/Right edge
smearedImage([1:L, end-L:end], :) = I([1:L, end-L:end], :); % Top/bottom edge
% Keep only inner blur
smearedImage(L:end-L,L:end-L) = min(smearedImage(L:end-L,L:end-L),double(I(L:end-L,L:end-L)));
figure
imshow(smearedImage,[]);
title(num2str(THETA(i)*180/pi))
set(gcf, 'Units', 'Normalized', 'OuterPosition', [0 0 1 1]);
end
I have solved a system of two second-order differential equations using an implementation of Euler's method in Julia. The below code shows how Euler's method has been called to solve the system in question.
θ1 = 1.1900518004210798; θ2 = 0.3807445263738167
f(t, y) = [y[2], -2(y[1] - θ1) - 4y[2] + 0.5sin(3pi*t),
y[4], -2(y[3] - θ2) - 4(y[4] + abs(y[2])) + 0.5sin(3pi*t)]
y0 = [pi/2, 0, pi/6, 0]; t0 = 0; tFinal = 50; h = 0.001
res = euler(f, y0, t0, tFinal, h)
The result, res, is a vector of four numbers
1.18798735437173
-0.0458294959470722
0.31530569612003573
-0.049213402534541074
The first entry is the angle that the bottom line segment forms with the x-axis while the third entry is the angle that the two line segments form with one another (see below figure).
To create this plot I called plot_robotarm([res[1], res[3]]) which is implemented according to the below code.
function plot_robotarm(thetav)
# Plots a robotarm with angles thetav
R = 1;
xv=zeros(length(thetav)+1)
yv=zeros(length(thetav)+1)
for i in 1:length(thetav)
xv[i+1]=xv[i]+R*cos(thetav[i])
yv[i+1]=yv[i]+R*sin(thetav[i])
end
# Plot with colors
opts = (:circle, 10, 1., :blue, stroke(7, 1., :red))
plt = plot(xv, yv,
marker = opts,
c = :red,
w = 5,
legend = false,
xlims = (0, 2.0),
ylims = (0, 2.0))
display(plt)
end
How can I create an animation that visualizes how consecutive iterations of Euler's method make the robot arm (i.e. the two line segments) move toward the final point at t = 50? (I do not need to plot every iteration, just enough so that it makes for an animation that captures the movement of the robot arm.)
You can use ffmpeg and Luxor.jl's animation features to make an animated GIF. The frame function needs to be modified to reflect graphical display of each step in your program. See the docs for Luxor for more.
using Luxor
using Colors
using BoundaryValueDiffEq
# constants for differential equations and movie
const g = 9.81
const L = 1.0 # pendulum length in meters
const bobd = 0.10 # pendulum bob diameter in meters
const framerate = 50.0 # intended frame rate/sec
const t0 = 0.0 # start time (s)
const tf = 2.3 # end simulation time (s)
const dtframe = 1.0/framerate # time increment per frame
const tspan = LinRange(t0, tf, Int(floor(tf*framerate))) # array of time points in animation
const bgcolor = "black" # gif background
const leaderhue = (0.80, 0.70, 0.20) # gif swing arm hue light gold
const hslcolors = [HSL(col) for col in (distinguishable_colors(
Int(floor(tf*framerate)+3),[RGB(1,1,1)])[2:end])]
const giffilename = "pendulum.gif" # output file
# differential equations copied from docs of DifferentialEquations.jl
simplependulum!(du, u, p, t) = (θ=u[1]; dθ=u[2]; du[1]=dθ; du[2]=-(g/L)*sin(θ))
bc1!(residual, u, p, t) = (residual[1] = u[div(end,2)][1] + pi/2; residual[2] = u[end][1] - pi/2)
bvp1 = TwoPointBVProblem(simplependulum!, bc1!, [pi/2,pi/2], (tspan[1],tspan[end]))
sol2 = solve(bvp1, GeneralMIRK4(), dt=dtframe)
# movie making background
backdrop(scene, framenumber) = background(bgcolor)
function frame(scene, framenumber)
u1, u2 = sol2.u[framenumber]
y, x = L*cos(u1), L*sin(u1)
sethue(leaderhue)
poly([Point(-4.0, 0.0), Point(4.0, 0.0),
Point(160.0x,160.0y)], :fill)
sethue(Colors.HSV(framenumber*4.0, 1, 1))
circle(Point(160.0x,160.0y), 160bobd, :fill)
text(string("frame $framenumber of $(scene.framerange.stop)"),
Point(0.0, -190.0),
halign=:center)
end
muv = Movie(400, 400, "Pendulum Demo", 1:length(tspan))
animate(muv, [Scene(muv, backdrop),
Scene(muv, frame, easingfunction=easeinoutcubic)],
creategif=true, pathname=giffilename)
I have two polygon images defined by 25 control points. I want to replace one polygon by another one in matlab. Below is an example of TC and BP.
I have added the code. I am not happy with the output texture in the replaced area. Also, I found the that if the polygon shape of the second image is smaller than the first image polygon shape then the output looks very bad.
clc;clear all;close all
im_original = imread('tc.jpg');
im_original=im2double(im_original);
%% ROI (X,Y) coordinates, variable name (pt_original)
load('tc.mat');
im_morphed = imread('bp.jpg');
img_morphed=im2double(im_morphed);
%% ROI (X,Y) coordinates, variable name (pt_morphed)
load('bp.mat');
%% Replace Face
[img_proc,mask] = defineRegion(im_original,pt_original);
img_morphed_proc = histeq_rgb(img_morphed, im_original, mask, mask);
sigma = 5;
se = strel('square',sigma);
mask = imerode(mask,se);
w = fspecial('gaussian',[50 50],sigma);
mask = imfilter(double(mask),w);
img_result = bsxfun(#times,double(img_morphed_proc),double(mask)) + bsxfun(#times,double(im_original),double(1-mask));
imshow(img_result)
function [img_proc,mask] = defineRegion(img, landmark)
sz = size(img);
k =convhull(landmark(:,2),landmark(:,1));
[YY,XX] = meshgrid(1:sz(1),1:sz(2));
in = inpolygon(XX(:),YY(:),landmark(k,1),landmark(k,2));
mask = reshape(in,[sz(2),sz(1)])';
img_proc = bsxfun(#times,im2double(img),double(mask));
end
function img_proc = histeq_rgb(img_src, img_dest, mask_src, mask_dest)
img_proc = img_src;
for i = 1 : 3
tmp_src = img_src(:,:,i);
tmp_src = tmp_src(mask_src);
tmp_dest = img_dest(:,:,i);
tmp_dest = tmp_dest(mask_dest);
t = histeq(tmp_src,imhist(tmp_dest));
tmp_proc = img_proc(:,:,i);
tmp_proc(mask_src) = t;
img_proc(:,:,i) = tmp_proc;
end
end
Output Image
I have lena image in Matlab. First I need to find the centroid C, and then divide the image into equal number of parts. I can calculate the centroid of the image but from that how can I divide the image into equal number of parts as shown below. Please anyone help me.
Thanks
Using poly2mask to create binary sectors and using the resulting sectors for indexing
Code:
im = imread('peppers.png');
r = 300;
out1 = ones(max(size(im,1),r*2)+2,max(size(im,2),r*2)+2,3).*255;
xoffset = floor((size(out1,2)-size(im,2))/2);
yoffset = floor((size(out1,1)-size(im,1))/2);
out1(yoffset:yoffset+size(im,1)-1,xoffset:xoffset+size(im,2)-1,:) = im(:,:,:);
im = out1;
cy = floor(size(im,1)/2);
cx = floor(size(im,2)/2);
figure;
imshow(uint8(im));
hold on
pos = [cx-r+1 cy-r+1 r*2 r*2];
rectangle('Position',pos,'Curvature',[1 1]);
x1 = [-r, 0, -r*cosd(45), -r*cosd(45); r, 0, r*cosd(45), r*cosd(45)]+cx+1;
y1 = [0, -r, -r*sind(45), r*sind(45); 0, r, r*sind(45), -r*sind(45)]+cy+1;
plot(x1,y1);
hold off
figure;
for i = 0:45:315
t = linspace(-i,-i-45,128);
x = [cx, cx+r*cosd(t), cx];
y = [cy, cy+r*sind(t), cy];
bw = poly2mask( x, y, size(im,1),size(im,2));
bw = repmat(bw,1,1,3);
out = ones(size(im,1),size(im,2),size(im,3)).*155;
out(bw) = im(bw);
subplot(2,4,(i/45)+1); imshow(uint8(out));
end;
Results:
Original Image
Partitions drawn over Original Image
Segments of the image
Update
for getting pixel values of the lines, by using Bresenham function from here
figure;
bw1 = zeros(size(im,1),size(im,2));
outmat = zeros(size(bw1));
[X,Y] = bresenham(cx+1-r,cy+1,cx+1+r,cy+1);
ind = sub2ind(size(outmat), Y, X);
outmat(ind) = 1;
[X,Y] = bresenham(cx+1,cy+1-r,cx+1,cy+1+r);
ind = sub2ind(size(outmat), Y, X);
outmat(ind) = 1;
[X,Y] = bresenham(cx+1-r*cosd(45),cy+1-r*sind(45),cx+1+r*cosd(45),cy+1+r*sind(45));
ind = sub2ind(size(outmat), Y, X);
outmat(ind) = 1;
[X,Y] = bresenham(cx+1-r*cosd(45),cy+1+r*sind(45),cx+1+r*cosd(45),cy+1-r*sind(45));
ind = sub2ind(size(outmat), Y, X);
outmat(ind) = 1;
se = strel('disk',5); %// change the '5' value to affect thickness of the line
outmat = imdilate(outmat,se);
outmat = repmat(boolean(outmat),1,1,3);
outmat1 = zeros(size(outmat));
outmat1(outmat) = im(outmat);
imshow(uint8(outmat1));
Pixel values under each lines
Check the following code. I just did it for a grayscale image. You can now change it to a color image as well. Check and pls confirm this is what you wanted.
clear all;
i = rgb2gray(imread('hestain.png'));
imshow(i);
cr = floor(size(i,1)/2);
cl = floor(size(i,2)/2);
r = min(cr, cl);
a = 90;
r1 = cr;
c1 = size(i,2);
v1=[c1 r1]-[cl cr];
i2 = zeros(size(i,1),size(i,2),ceil(360/a));
for ri = 1:size(i,1)
for ci = 1:size(i,2)
v2=[ci ri]-[cl cr];
a2 = mod(-atan2(v1(1)*v2(2)-v1(2)*v2(1), v1*v2'), 2*pi) * 180/pi;
d2 = pdist([ci ri; cl cr],'euclidean');
if d2<=r
if ceil(a2/a)==0
a2 =1;
end
i2(ri,ci,ceil(a2/a)) = i(ri,ci);
end
end
end
figure;
for i=1:360/a
subplot(2,180/a,i);
imshow(mat2gray(i2(:,:,i)));
end
Sample output:
I can't find anywhere an explaination about how to use the frames option for ExtrudeGeometry in Three.js. Its documentation says:
extrudePath — THREE.CurvePath. 3d spline path to extrude shape along. (creates Frames if (frames aren't defined)
frames — THREE.TubeGeometry.FrenetFrames. containing arrays of tangents, normals, binormals
but I don't understand how frames must be defined. I think using the "frames" option, passing three arrays for tangents, normals and binormals (calculated in some way), but how to pass them in frames?... Probably (like here for morphNormals):
frames = { tangents: [ new THREE.Vector3(), ... ], normals: [ new THREE.Vector3(), ... ], binormals: [ new THREE.Vector3(), ... ] };
with the three arrays of the same lenght (perhaps corresponding to steps or curveSegments option in ExtrudeGeometry)?
Many thanks for an explanation.
Edit 1:
String.prototype.format = function () {
var str = this;
for (var i = 0; i < arguments.length; i++) {
str = str.replace('{' + i + '}', arguments[i]);
}
return str;
}
var numSegments = 6;
var frames = new THREE.TubeGeometry.FrenetFrames( new THREE.SplineCurve3(spline), numSegments );
var tangents = frames.tangents,
normals = frames.normals,
binormals = frames.binormals;
var tangents_list = [],
normals_list = [],
binormals_list = [];
for ( i = 0; i < numSegments; i++ ) {
var tangent = tangents[ i ];
var normal = normals[ i ];
var binormal = binormals[ i ];
tangents_list.push("({0}, {1}, {2})".format(tangent.x, tangent.y, tangent.z));
normals_list.push("({0}, {1}, {2})".format(normal.x, normal.y, normal.z));
binormals_list.push("({0}, {1}, {2})".format(binormal.x, binormal.y, binormal.z));
}
alert(tangents_list);
alert(normals_list);
alert(binormals_list);
Edit 2
Times ago, I opened this topic for which I used this solution:
var spline = new THREE.SplineCurve3([
new THREE.Vector3(20.343, 19.827, 90.612), // t=0
new THREE.Vector3(22.768, 22.735, 90.716), // t=1/12
new THREE.Vector3(26.472, 23.183, 91.087), // t=2/12
new THREE.Vector3(27.770, 26.724, 91.458), // t=3/12
new THREE.Vector3(31.224, 26.976, 89.861), // t=4/12
new THREE.Vector3(32.317, 30.565, 89.396), // t=5/12
new THREE.Vector3(31.066, 33.784, 90.949), // t=6/12
new THREE.Vector3(30.787, 36.310, 88.136), // t=7/12
new THREE.Vector3(29.354, 39.154, 90.152), // t=8/12
new THREE.Vector3(28.414, 40.213, 93.636), // t=9/12
new THREE.Vector3(26.569, 43.190, 95.082), // t=10/12
new THREE.Vector3(24.237, 44.399, 97.808), // t=11/12
new THREE.Vector3(21.332, 42.137, 96.826) // t=12/12=1
]);
var spline_1 = [], spline_2 = [], t;
for( t = 0; t <= (7/12); t+=0.0001) {
spline_1.push(spline.getPoint(t));
}
for( t = (7/12); t <= 1; t+=0.0001) {
spline_2.push(spline.getPoint(t));
}
But I was thinking the possibility to set the tangent, normal and binormal for the first point (t=0) of spline_2 to be the same of last point (t=1) of spline_1; so I thought if that option, frames, could return in some way useful for the purpose. Could be possible to overwrite the value for a tangent, normal and binormal in the respective list, to obtain the same value for the last point (t=1) of spline_1 and the first point (t=0) of spline_2, so to guide the extrusion? For example, for the tangent at "t=0" of spline_2:
tangents[0].x = 0.301;
tangents[0].y = 0.543;
tangents[0].z = 0.138;
doing the same also for normals[0] and binormals[0], to ensure the same orientation for the last point (t=1) of spline_1 and the first one (t=0) of spline_2
Edit 3
I'm trying to visualize the tangent, normal and binormal for each control point of "mypath" (spline) using ArrowHelper, but, as you can see in the demo (on scene loading, you need zoom out the scene slowly, until you see the ArrowHelpers, to find them. The relative code starts from line 122 to line 152 in the fiddle), the ArrowHelper does not start at origin, but away from it. How to obtain the same result of this reference demo (when you check the "Debug normals" checkbox)?
Edit 4
I plotted two splines that respectively end (blue spline) and start (red spline) at point A (= origin), displaying tangent, normal and binormal vectors at point A for each spline (using cyan color for the blue spline's labels, and yellow color for the red spline's labels).
As mentioned above, to align and make continuous the two splines, I thought to exploit the three vectors (tangent, normal and binormal). Which mathematical operation, in theory, should I use to turn the end face of blue spline in a way that it views the initial face (yellow face) of red spline, so that the respective tangents (D, D'-hidden in the picture), normals (B, B') and binormals (C, C') are aligned? Should I use the ".setFromUnitVectors (vFrom, VTO)" method of quaternion? In its documentation I read: << Sets this quaternion to the rotation required to rotate vFrom direction vector to vector direction VTO ... vFrom VTO and are assumed to be normalized. >> So, probably, I need to define three quaternions:
quaternion for the rotation of the normalized tangent D vector in the direction of the normalized tangent D' vector
quaternion for the rotation of the normalized normal B vector in the direction of the normalized normal B' vector
quaternion for the rotation of the normalized binormal C vector in the direction of the normalized binormal C' vector
with:
vFrom = normalized D, B and C vectors
VTO = normalized D', B' and C' vectors
and apply each of the three quaternions respectively to D, B and C (not normalized)?
Thanks a lot again
Edit 5
I tried this code (looking in the image how to align the vectors) but nothing has changed:
var numSegments_1 = points_1.length; // points_1 = list of points
var frames_1 = new THREE.TubeGeometry.FrenetFrames( points_1_spline, numSegments_1, false ); // path, segments, closed
var tangents_1 = frames_1.tangents,
normals_1 = frames_1.normals,
binormals_1 = frames_1.binormals;
var numSegments_2 = points_2.length;
var frames_2 = new THREE.TubeGeometry.FrenetFrames( points_2_spline, numSegments_2, false );
var tangents_2 = frames_2.tangents,
normals_2 = frames_2.normals,
binormals_2 = frames_2.binormals;
var b1_b2_angle = binormals_1[ binormals_1.length - 1 ].angleTo( binormals_2[ 0 ] ); // angle between binormals_1 (at point A of spline 1) and binormals_2 (at point A of spline 2)
var quaternion_n1_axis = new THREE.Quaternion();
quaternion_n1_axis.setFromAxisAngle( normals_1[ normals_1.length - 1 ], b1_b2_angle ); // quaternion equal to a rotation on normal_1 as axis
var vector_b1 = binormals_1[ binormals_1.length - 1 ];
vector_b1.applyQuaternion( quaternion_n1_axis ); // apply quaternion to binormals_1
var n1_n2_angle = normals_1[ normals_1.length - 1 ].angleTo( normals_2[ 0 ] ); // angle between normals_1 (at point A of spline 1) and normals_2 (at point A of spline 2)
var quaternion_b1_axis = new THREE.Quaternion();
quaternion_b1_axis.setFromAxisAngle( binormals_1[ binormals_1.length - 1 ], -n1_n2_angle ); // quaternion equal to a rotation on binormal_1 as axis
var vector_n1 = normals_1[ normals_1.length - 1 ];
vector_n1.applyQuaternion( quaternion_b1_axis ); // apply quaternion to normals_1
nothing in this other way also:
var numSegments_1 = points_1.length; // points_1 = list of points
var frames_1 = new THREE.TubeGeometry.FrenetFrames( points_1_spline, numSegments_1, false ); // path, segments, closed
var tangents_1 = frames_1.tangents,
normals_1 = frames_1.normals,
binormals_1 = frames_1.binormals;
var numSegments_2 = points_2.length;
var frames_2 = new THREE.TubeGeometry.FrenetFrames( points_2_spline, numSegments_2, false );
var tangents_2 = frames_2.tangents,
normals_2 = frames_2.normals,
binormals_2 = frames_2.binormals;
var quaternion_n1_axis = new THREE.Quaternion();
quaternion_n1_axis.setFromUnitVectors( binormals_1[ binormals_1.length - 1 ].normalize(), binormals_2[ 0 ].normalize() );
var vector_b1 = binormals_1[ binormals_1.length - 1 ];
vector_b1.applyQuaternion( quaternion_n1_axis );
var quaternion_b1_axis = new THREE.Quaternion();
quaternion_b1_axis.setFromUnitVectors( normals_1[ normals_1.length - 1 ].normalize(), normals_2[ 0 ].normalize() );
var vector_n1 = normals_1[ normals_1.length - 1 ];
vector_n1.applyQuaternion( quaternion_b1_axis );