【问题标题】:Repeat image along circle沿圆圈重复图像
【发布时间】:2014-04-01 19:01:48
【问题描述】:

如何沿圆圈重复图像?请注意,它也应该有点失真。我想要做到的是:我一直在研究一种 POV LED 设计,它可以拍摄图像并在整个旋转时沿着一串 LED 闪烁。当你看显示器时,图像有点扭曲,沿着圆圈的内部挤压并在外部拉伸一点。我想重新创建它。

红色圆圈仅供参考,大小相同。我可能也会将它留在生成的复合材料中。图像沿圆形路径重复的频率应该可以根据原始图像的实际宽度(以及我是否在每个副本之间添加中断)进行调整。例如,有些图像彼此相邻,没有休息,其他需要休息的。所以我需要一种方法来定义它。

使用黄色对角线,我不想在图像重复时出现中断。我将白色边缘留在顶部以显示它是如何变形的。

如何使用 Magick++ 完成此任务?最终,我会将代码合并到一个大型应用程序中,该应用程序使用 Magick++ 来处理用户为 POV LED 显示屏导入的图像。

谢谢!

【问题讨论】:

    标签: imagemagick magick++


    【解决方案1】:

    是的,您可以使用Magick::Image.distort 完成围绕圆圈平铺图像。尽管由于您对 POV 项目有非常本地化的要求,因此预计会进行一些试验和错误。

    沿圆圈重复图像

    ArcDistortion 的示例同样适用于Magick++。确保启用虚拟像素方法,并使用 360 度圆弧扭曲给定图像。我使用的是图像“pattern:CHECKERBOARD”,但你会使用“tile:image_source.png”。

    Magick::Image MyArc;
    MyArc.read("pattern:CHECKERBOARD");
    MyArc.size("600x45");
    MyArc.virtualPixelMethod(Magick::WhiteVirtualPixelMethod);
    const double arcArgs[1] = {360};
    MyArc.distort(Magick::ArcDistortion,1, arcArgs,Magick::MagickTrue);
    MyArc.write("out.png");
    

    这将为您提供一个沿圆圈重复的图像。

    保护内圈

    控制内外圆的大小。将第三个和第四个参数应用于失真方法。

    const double arcArgs[4] = {360,0,200,100};
    MyArc.distort(Magick::ArcDistortion,4, arcArgs,Magick::MagickTrue);
    

    带有预处理的自定义图像

    就添加空白、填充、出血和调整图像重复而言。这些都需要在电弧变形之前进行预处理。

    Magick::Image SourceImage;
    SourceImage.read("me.png");
    SourceImage.resize("45x45");
    // Add whitespace between repeating image
    SourceImage.extent(Magick::Geometry(100,45));
    
    // Resize image to be "long" enough to bend around arc.
    SourceImage.size("600x45");
    // PrePrecess image to tile horizontally with Edge Virtual Pixel
    SourceImage.virtualPixelMethod(Magick::HorizontalTileEdgeVirtualPixelMethod);
    const double tileArgs[1] = {0};
    SourceImage.distort(Magick::ScaleRotateTranslateDistortion,1,tileArgs,Magick::MagickTrue);
    
    // Distort around circle
    SourceImage.virtualPixelMethod(Magick::WhiteVirtualPixelMethod);
    const double arcArgs[4] = {360,0,200,100};
    SourceImage.distort(Magick::ArcDistortion,4, arcArgs,Magick::MagickTrue);
    SourceImage.write("out.png");
    

    如果 POV 问题可以通过 fun math 解决,请记住很多。

    【讨论】:

    • 您好,感谢您的详细解释。如果你不介意,你能给我解释几行吗?具体来说,最后一段代码适用于您的图像。我了解您将其调整为 45x45 图像的位置。下一行,为什么要将其扩展到 100x45?那是在图像之间添加空白吗?接下来,当您再次将其调整为 600x45 时,这是为什么呢?
    • 用额外的线路 cmets 更新了答案。实际上,“600x45”的宽度应该是所需的周长。它应该被调整以匹配 POV 中的兴趣点,但您可以通过计算 (bottomRadius * 2 + imageHeight / 2) * PI
    • 谢谢!现在我将继续我的下一步,为它添加一些逻辑。比宽高的图像需要更频繁地重复,而比高宽的图像需要更少重复。现在我是手动做的,但我希望最终能拿出一组平均数字来自动处理它。我正在考虑计算比例并从那里开始。这部分是关于图像的可视化(它在 POV 棒上旋转后的样子。)再次感谢您的帮助!
    【解决方案2】:

    我想我明白了。所以这是我现在正在使用的代码的 sn-p:

    Magick::Image srcImage;
    srcImage.read("001.png");
    srcImage.resize("x100");      // I want images at least 100 pixels high
    Magick::Color color(0, 0, 0); // images should always be on a black background
    
    // to add space beween a repeating image, add a value to .columns()
    // for example:
    // srcImage.extent(Magick::Geometry(srcImage.columns() + 10, 100), color);
    // will add 10 pixels of space or padding after each image repeat
    srcImage.extent(Magick::Geometry(srcImage.columns(), 100), color);
    
    // preprocess
    // .columns() is multiplied by the amount of times the image repeats in the circle
    // for example, this repeats the image 8 times:
    // srcImage.size(Magick::Geometry(srcImage.columns() * 8, 100));
    srcImage.size(Magick::Geometry(srcImage.columns() * 8, 100));
    srcImage.virtualPixelMethod(Magick::HorizontalTileEdgeVirtualPixelMethod);
    const double tileArgs[1] = {0};
    srcImage.distort(Magick::ScaleRotateTranslateDistortion, 1, tileArgs, Magick::MagickTrue);
    
    // distort
    srcImage.virtualPixelMethod(Magick::BlackVirtualPixelMethod);
    const double arcArgs[4] = {360, 0, 98, 30};
    srcImage.distort(Magick::ArcDistortion, 4, arcArgs, Magick::MagickTrue);
    srcImage.write("001-out.png");
    

    【讨论】:

    • 看起来不错!您应该 +1 我的回答,但接受您自己的回答而不是我的回答。这将帮助未来的读者确定哪个解决方案解决了您最初的问题。
    • Hrm,我在圆的底部得到了一条黑色像素线。它看起来像是在弧形变形后边缘最终会合的地方。有任何想法吗?难道是因为之前的操纵?当我第一次读入图像时,我会检查它的高度是否超过了某个阈值。如果是这样,我将调整它的大小以匹配特定的高度。然后我会扩展它,最后做弧形失真。其中一个边缘是否会以模糊的黑色像素列结束,然后在失真后变得更加明显?
    • 任何像素瑕疵都可能在失真过程中被夸大。它们通常需要在预处理期间固定在源图像中。查看文章@imagemagick.org/Usage/misc,尤其是Virtual Pixels 部分。在我的回答中,我暗示了bleeding,这意味着将图像扩展到所需边缘之外,应用失真,然后用蒙版修剪。为了便于查看,我通常将出血保留在最终图像中,并在显示时调整视口。
    • 对,我知道图像的边缘没有伪影,我确定了这一点。但是,不知道当它们第一次调整大小时,一个或两个边缘是否最终会产生伪影,尽管我怀疑是这种情况。进行出血不会(总是)起作用,因为其中一些图像需要在边缘相遇时匹配,并且被修剪的出血会导致不匹配。所以我认为我在这里的选择是读取、扩展、扭曲和最后调整大小,而不是读取、调整大小、扩展和扭曲。我会试试看会发生什么。
    猜你喜欢
    • 1970-01-01
    • 2015-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-10
    • 2020-09-03
    • 2020-12-24
    相关资源
    最近更新 更多