处理中的变形图像效果

发布于 2025-01-09 03:17:10 字数 1227 浏览 1 评论 0原文

我想在处理中构建一种图像变形工具。类似于您在此链接中看到的内容:

https://giphy.com/gifs/ Painting-morph-oil-c8ygOpL64UDuw

我实现此目标的第一步是构建一个二维像素网格。像素充满颜色。填充颜​​色是通过使用 get(); 从图像 (PImage img1;) 读取颜色来创建的。功能。这就是我用像素重新创建图像的方法。在第二步中,我想我会使用 lerp();函数为各个像素提供第二个图像的颜色(PImage img2;) - 我认为这会创建所需的变形效果。但我错了!整个事情有效 - 但效果只是两个图像之间发生淡入。而且没有变形。当这种变形效果出现时,像素究竟会发生什么?我如何在处理中重新创建它?

float pixel;
float pixelsize;
PImage img1;
PImage img2;
float counter;

void setup() {
  size(1080, 1080);
  pixel = 100;
  pixelsize = width/pixel;
  noStroke();
  img1 = loadImage("0.jpg");
  img2 = loadImage("1.jpg");
  counter = 0;
}


void draw() {
  background(255);

  for (int y = 0; y < pixel; y++) {
    for (int x = 0; x < pixel; x++) {
      color c1 = img1.get(int(pixelsize*x), int(pixelsize*y));
      color c2 = img2.get(int(pixelsize*x), int(pixelsize*y));

      color from = c1;
      color to = c2;
      color interA = lerpColor(from, to, counter);

      pushMatrix();
      translate(pixelsize*x, pixelsize*y);
      fill(interA);
      rect(0, 0, pixelsize, pixelsize);
      popMatrix();
    }
  }
  counter= counter + 0.01;
}

I would like to build a kind of image morphing tool in Processing. Similar to what you can see in this link:

https://giphy.com/gifs/painting-morph-oil-c8ygOpL64UDuw

My first step to achieve this was to build a two-dimensional grid of pixels. The pixels are filled with colour. The fill colour is created by reading colour from an image (PImage img1;) with the get(); function. This is how I recreated an image with my pixels. In the second step, I thought I would use the lerp(); function to give the respective pixels the colour of a second image (PImage img2;) - I thought this would create the desired morph effect. But I was wrong! The whole thing works - but the effect is only that a fade-in takes place between the two images. And no morphing. What exactly happens to pixels while this morph effect? How could I recreate it in Processing?

float pixel;
float pixelsize;
PImage img1;
PImage img2;
float counter;

void setup() {
  size(1080, 1080);
  pixel = 100;
  pixelsize = width/pixel;
  noStroke();
  img1 = loadImage("0.jpg");
  img2 = loadImage("1.jpg");
  counter = 0;
}


void draw() {
  background(255);

  for (int y = 0; y < pixel; y++) {
    for (int x = 0; x < pixel; x++) {
      color c1 = img1.get(int(pixelsize*x), int(pixelsize*y));
      color c2 = img2.get(int(pixelsize*x), int(pixelsize*y));

      color from = c1;
      color to = c2;
      color interA = lerpColor(from, to, counter);

      pushMatrix();
      translate(pixelsize*x, pixelsize*y);
      fill(interA);
      rect(0, 0, pixelsize, pixelsize);
      popMatrix();
    }
  }
  counter= counter + 0.01;
}

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

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

发布评论

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

评论(1

丘比特射中我 2025-01-16 03:17:10

事实上,这不是一项直接的任务。

你的方法并不是一个糟糕的开始:它将导致两个图像之间产生很好的交叉淡入淡出。

请记住,get() 可能会占用 CPU 资源。
但是,您可以使用 pixels[]

PImage img1;
PImage img2;
// transition image
PImage imgT;

void setup() {
  size(1080, 1080);
  
  img1 = loadImage("0.jpg");
  img2 = loadImage("1.jpg");
  // copy the 1st image (copies width/height as well)
  imgT = img1.get();
}


void draw() {
  background(255);
  // map transition amount to mouse X position
  float t = map(mouseX, 0, width, 0.0, 1.0);
  
  // make all pixels readable
  imgT.loadPixels();
  // lerp each pixel
  for(int i = 0 ; i < imgT.pixels.length; i++){
    imgT.pixels[i] = lerpColor(img1.pixels[i], img2.pixels[i], t);
  }
  // update all pixels in one go
  imgT.updatePixels();
  
  // display result
  image(imgT, 0, 0);
}

实现完整变形图像并不平凡。
我可以推荐两个选项来利用现有算法,但是这些选项也不适合初学者:

  1. ImageMagick 实现了 shepards 失真,并且有一个与 imagemagick 接口的 java 库:im4java。请注意,您需要下载预编译的 java 库并将 .jar 文件放在草图之上,并且处理输出可能需要时间:对于实时来说可能不可行(但是应该可以将各个帧保存到磁盘并组装它们作为 gif/电影/等。)
  2. 使用 OpenCV:有一个 OpenCV Face Morph 教程,包含 C++ 源代码或 Python 并且有一个处理 OpenCV 库。这需要将 c++/Python OpenCV 调用移植到 Java OpenCV API。

Indeed it is not a straight forward task.

You're approach is not a bad start: it would result in a nice crossfade between the two images.

Bare in mind get() can be costly on the CPU.
You can however use the pixels[]:

PImage img1;
PImage img2;
// transition image
PImage imgT;

void setup() {
  size(1080, 1080);
  
  img1 = loadImage("0.jpg");
  img2 = loadImage("1.jpg");
  // copy the 1st image (copies width/height as well)
  imgT = img1.get();
}


void draw() {
  background(255);
  // map transition amount to mouse X position
  float t = map(mouseX, 0, width, 0.0, 1.0);
  
  // make all pixels readable
  imgT.loadPixels();
  // lerp each pixel
  for(int i = 0 ; i < imgT.pixels.length; i++){
    imgT.pixels[i] = lerpColor(img1.pixels[i], img2.pixels[i], t);
  }
  // update all pixels in one go
  imgT.updatePixels();
  
  // display result
  image(imgT, 0, 0);
}

Implementing a full morph image is non-trivial.
I can recomend two options to make use of existing algorithms, however these options are also not beginner friendly:

  1. ImageMagick implements shepards distortion and there is a java library that interfaces with imagemagick: im4java. Note that you'd need to download the precompiled java library and drop the .jar file on top of your sketch and processing the output might take time: probably not feasible for realtime (however it should be possible to save individual frames to disk and assemble them as a gif/movie/etc.)
  2. Using OpenCV: there's an OpenCV Face Morph tutorial with source code in c++ or Python and there is a Processing OpenCV library. It would be a matter of porting the c++/Python OpenCV calls to the Java OpenCV API.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文