使用CImg使用线性插值填充颜色

时间:2018-02-04 06:25:40

标签: c++ colors interpolation cimg

“使用CImg,编写一个构建方形图像并为每个角分配颜色的程序。使用 线性插值,填充并着色方形中的每个像素,以便有一个平滑的着色 广场的整个区域“

我很难理解如何为每个角落选择一种颜色,并为正方形填充颜色。下面是我的代码,但它似乎随机放置颜色,我不能选择自己的颜色。在我现在的代码下面。

#include <iostream>
#include "CImg/CImg.h"

using namespace cimg_library;
using namespace std;

int main() {
  //Create an empty image
  CImg<unsigned char> square(255, 255, 1, 3, 0);

  for (int i = 0; i < 255; i++){
      for(int j = 0; j < 255; j++){
          //Red
          square(i,j,0,0) = i; 
          //Green
          square(i,j,0,1) = j;
          //Blue
          square(i,j,0,2) = i;                
      }
  }

  //Display and save filtered image
  CImgDisplay disp(square); 
  while (!disp.is_closed())
      disp.wait();   
  square.save("squareInterpolation.bmp");  
}

我的代码的结果:
image

我想要的结果(忽略白色边框):
image

非常感谢你!

1 个答案:

答案 0 :(得分:1)

目前,您的代码没有进行任何插值 - 它只是分配。插值是您知道图像极限值的位置,并计算这些已知值之间的值(使用公式)来填充未知值。

实际上,CImg将为您进行插值,恕我直言,优秀的工程师可以重复使用并回收经过良好测试的代码,因为它可以降低成本。因此,最简单的解决方案是创建红色,绿色,蓝色和白色角点的2x2图像(插值中的已知值),并让CImg使用插值将图像调整为255x255。

这可能是这样的:

#include <iostream>
#include <cstdlib>
#define cimg_display 0
#include "CImg.h"

using namespace cimg_library;
using namespace std;

#define INTERPOLATION_LINEAR            3
#define INTERPOLATION_CUBIC             5

#define BOUNDARY_DIRICHLET              0
#define BOUNDARY_NEUMANN                1

int main() {
   // Create 2x2 image with Red, Green, Blue and White pixels
   CImg<unsigned char> image(2,2,1,3,0);
   image(0,0,0,0)=255;  // top-left is Red
   image(1,0,0,1)=255;  // top-right is Green
   image(0,1,0,2)=255;  // bottom-left is Blue
   image(1,1,0,0)=255;  // bottom-right is white
   image(1,1,0,1)=255;  // bottom-right is white
   image(1,1,0,2)=255;  // bottom-right is white

   // Let CImg do the interpolation for us - because smart engineers re-use well tested code
   CImg<unsigned char> result=image.resize(255,255,-100,-100,INTERPOLATION_LINEAR,BOUNDARY_DIRICHLET);

   // Save result image as NetPBM PNM - no libraries required
   result.save_pnm("result.pnm");
}

enter image description here

我想这不是你期望的方式,所以我会把这个解决方案和我自己实现插值的另一个解决方案结合起来。以下是您可以在Wikipedia article on Bilinear Interpolation中使用的公式。

enter image description here

可以这样实现:

#include <iostream>
#include <cstdlib>
#define cimg_display 0
#include "CImg.h"

using namespace cimg_library;
using namespace std;

int main() {
   // Create 256x256 image with Red, Green, Blue and White pixels
   CImg<unsigned char> image(256,256,1,3,0);
   image(0,0,0,0)=255;      // top-left is Red
   image(255,0,0,1)=255;    // top-right is Green
   image(0,255,0,2)=255;    // bottom-left is Blue
   image(255,255,0,0)=255;  // bottom-right is white
   image(255,255,0,1)=255;  // bottom-right is white
   image(255,255,0,2)=255;  // bottom-right is white

   // Fill inner area by interpolation
   for(int r=0;r<256;r++){                   // "r" for "row" 
      for(int c=0;c<256;c++){                // "c" for "column"
         for(int b=0;b<3;b++){               // "b" for "band" in my head
            float oneMinusX=(255-r)/255.0;
            float oneMinusY=(255-c)/255.0;
            image(r,c,0,b)=image(0,0,0,b)*oneMinusX*oneMinusY +
                     image(255,0,0,b)*oneMinusY*r/255.0 +
                     image(0,255,0,b)*oneMinusX*c/255.0 +
                     image(255,255,0,b)*r*c/(255.0*255.0);
         }
      }
   }

   // Save result image as NetPBM PNM - no libraries required
   image.save_pnm("result.pnm");
}