根据不同方向的线条扭曲图像

发布于 2024-11-10 16:19:35 字数 2205 浏览 7 评论 0原文

我想根据不同方向的线条来扭曲图像:

  1. 对于输入图像上的每条线,我可以获得该线​​上像素的坐标,
  2. 然后将这些像素映射到扭曲的图像,以便每条线现在都是一个专栏。

我会使用 interp2 因为我已经有了 XYZ,并且我会制作 XiYi 以及为每条线获取的坐标。但是,您将如何:

  • 避免创建索引遍及行数的 for 循环?
  • 确保输出扭曲图像中的每一列大小相同?
  • 用径向线对输入图像进行采样?
  • 我认为最难的问题是,即使我使用不同的方向,如何保持邻域结构:例如,输入图像左侧部分的水平线(行)和右侧部分的径向线?

这里的输入图像是一个轮胎,有一个漂亮的圆圈图案。我可以从轮胎中心制作径向线,我想获得一个新图像,其列是径向线的像素。

这是我到目前为止的代码(还没有 interp2 因为我还没有解决上面解释的问题)。

close all

%% Image
Z = imread('tire.tif');
% The corresponding mesh
sz = size(Z);
[X,Y] = meshgrid(1:sz(2), 1:sz(1));

%% Line
lineEquation = @(c, v) (v(1)*(X-c(2))+v(2)*(Y-c(1)))/norm(v);
getLine = @(c, v) abs(lineEquation(c, v))<1/2;
% Example
c = [93, 109];
v = [2, 1];
line = getLine(c, v);

%% Circle
circleEquation = @(c, r) ((X-c(2)).^2+(Y-c(1)).^2-r^2)/r^2;
getCircle = @(c, r) abs(circleEquation(c, r))<1/r;
% Example
r = 24;
circle = getCircle(c, r);

%% Plot a sequence of line
figure;
for delta = -1:0.1:1
        v = [0.1, delta];
        line_delta = getLine(c, v);
        Z_line = Z;
        Z_line(line_delta) = 255;
        imagesc(Z_line);
        colormap('gray');
        pause(0.05);
end

%% Plot examples
figure;

subplot(221);
imagesc(Z); 
title('Image');

subplot(222);
Z_line = Z;
Z_line(line) = 255;
imagesc(Z_line);
title('Line');

subplot(223);
Z_circle = Z;
Z_circle(circle) = 255;
imagesc(Z_circle);
title('Circle');

subplot(224);
% TODO
title('Warped image');

colormap('gray');

以下是不同的输出:

Examples

Lines

Circles


这是扭曲的图像: Warped image

这是答案中的代码:

[ANG, RAD] = meshgrid(0:0.01:2*pi, 0:0.5:166);
XI = c(2) + cos(ANG).*RAD;
YI = c(1) + sin(ANG).*RAD;
WARPED = interp2(X, Y, double(Z), XI, YI);

WARPED(isnan(WARPED))= max(WARPED(:));
imagesc(WARPED);
title('Warped image');
colormap('gray');

I would like to warp an image based on lines given with different orientations:

  1. for each line on the input image, I can get the coordinates of the pixels on the line
  2. then I would map these pixels to the warped image so that each line is now a column.

I would use interp2 since I already have X, Y and Z, and I would make Xi and Yi with the coordinates obtained for each line. However, how would you:

  • avoid making a for loop which index goes all over the number of lines?
  • make sure each column in the output warped image is the same size?
  • sample the input image with radial lines?
  • the hardest question in my opinion, how would you keep the neighbourhood structure even if I use different orientations : for instance, the horiontal lines (rows) of the left part of the input image, and the radial lines for the right part?

The input image here is a tire, there is this nice pattern of circles. I could make radial lines from the center of the tire and I would like to get a new image whose columns are the pixels from the radial lines.

Here is the code I have so far (no interp2 yet as I have not solved the problems explained above).

close all

%% Image
Z = imread('tire.tif');
% The corresponding mesh
sz = size(Z);
[X,Y] = meshgrid(1:sz(2), 1:sz(1));

%% Line
lineEquation = @(c, v) (v(1)*(X-c(2))+v(2)*(Y-c(1)))/norm(v);
getLine = @(c, v) abs(lineEquation(c, v))<1/2;
% Example
c = [93, 109];
v = [2, 1];
line = getLine(c, v);

%% Circle
circleEquation = @(c, r) ((X-c(2)).^2+(Y-c(1)).^2-r^2)/r^2;
getCircle = @(c, r) abs(circleEquation(c, r))<1/r;
% Example
r = 24;
circle = getCircle(c, r);

%% Plot a sequence of line
figure;
for delta = -1:0.1:1
        v = [0.1, delta];
        line_delta = getLine(c, v);
        Z_line = Z;
        Z_line(line_delta) = 255;
        imagesc(Z_line);
        colormap('gray');
        pause(0.05);
end

%% Plot examples
figure;

subplot(221);
imagesc(Z); 
title('Image');

subplot(222);
Z_line = Z;
Z_line(line) = 255;
imagesc(Z_line);
title('Line');

subplot(223);
Z_circle = Z;
Z_circle(circle) = 255;
imagesc(Z_circle);
title('Circle');

subplot(224);
% TODO
title('Warped image');

colormap('gray');

Here are different outputs:

Examples

Lines

Circles


Here is the warped image:
Warped image

Here is the code from the answer:

[ANG, RAD] = meshgrid(0:0.01:2*pi, 0:0.5:166);
XI = c(2) + cos(ANG).*RAD;
YI = c(1) + sin(ANG).*RAD;
WARPED = interp2(X, Y, double(Z), XI, YI);

WARPED(isnan(WARPED))= max(WARPED(:));
imagesc(WARPED);
title('Warped image');
colormap('gray');

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

明明#如月 2024-11-17 16:19:35

你的主要问题(我认为)是构建 interp2。您可以通过认识到在新图像中水平轴代表直线的角度,垂直轴代表距圆心的距离来构造这些,以便构造这些:

%% angle from 360 to 0, radius from 0 to 100 
%% resulting image will be 361 x 101 pixels
[ANG, RAD] = meshgrid(360:-1:0,0:100); 
%% I take the centre of the circle at (93, 109) Is this correct?
%% From there you can create XI and YI 
%% from the angle and radius you have at each point
XI = ones(size(ANG))*93 + cos(ANG/(2*PI)).*RAD;
YI = ones(size(ANG))*109 + sin(ANG/(2*PI)).*RAD;

WARPED = interp2(X,Y,Z, XI, YI)

输出将严重扭曲(当然),因为每个半径处的圆被拉伸为相同的长度。沿着这条线,失真将是最小的。如果一切顺利并且我的数学能力还没有离开我,这应该会给你一个轮胎的展开图像,沿着从中心到右侧的线切割。

Your main problem (I think) is constructing matrices XI and YI needed for interp2. You construct these by realising that in your new image the horizontal axis represents the angle of the line, and the vertical axis represents the distance from the centre of the circle so to construct those:

%% angle from 360 to 0, radius from 0 to 100 
%% resulting image will be 361 x 101 pixels
[ANG, RAD] = meshgrid(360:-1:0,0:100); 
%% I take the centre of the circle at (93, 109) Is this correct?
%% From there you can create XI and YI 
%% from the angle and radius you have at each point
XI = ones(size(ANG))*93 + cos(ANG/(2*PI)).*RAD;
YI = ones(size(ANG))*109 + sin(ANG/(2*PI)).*RAD;

WARPED = interp2(X,Y,Z, XI, YI)

The output will be heavily distorted (of course) because the circle at each radius is stretched to be the same length. Along the lines distortion will be minimal. If all goes well and my math-fu hasn't left me this should give you a rolled out image of the tire, cut on the line from the centre to the right.

多情癖 2024-11-17 16:19:35

最好的办法:
使用二阶多项式变换将所有圆变换为直线,然后剪出您需要的直线。
使用 2 个带有参数“多项式”的 Matlab 命令 cp2tform() 和 imtransform()
在变换 T 内设置 x^2 和 y^2 的值 1 以创建圆并进行平移以定义轮胎的中心像素。

抱歉,我不提供代码,因为我是通过 iPhone 接听的。
Ps 检查 Matlab 有关多项式和保角变换的帮助。他们正是按照您的需要做的。

The best way:
Use polynomial transformation of second order to transform all the circles to lines and then just cut out the lines you need.
Use 2 Matlab commands cp2tform() with parameter 'polynomial' and imtransform()
Set inside the transformation T the values 1 for x^2 and y^2 to create a circle and translation to define the center pixel of the tire.

Sorry that I don't supply code, since I answer from iPhone.
P.s. Check Matlab help about polynomial and conformal transformation. They do exactly what you need.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文