ZQlib都能幹些什麼之五:紋理合成

ZQlib都能幹些什麼之五:紋理合成

4 人贊了文章

大四保研之後跟著研一的學生上過圖形學課,裡面講到紋理合成,自己實現了兩種。

一、基於GraphCut的紋理合成

原理可以參考論文Graphcut Textures: Image and Video Synthesis Using Graph Cuts, SIGGRAPH 2003

圖割演算法改自開源的max-flow,下載地址我忘了在哪了,用過那個庫的讀者估計可以根據我代碼里的注釋看出是哪個庫github.com/zuoqing1988/

基於GraphCut的紋理合成類定義在文件github.com/zuoqing1988/

使用示例github.com/zuoqing1988/

#include "ZQ_GraphCutForTexture.h"#include "ZQ_DoubleImage.h"#include "ZQ_ImageIO.h"#include <stdio.h>#include <stdlib.h>using namespace ZQ;int main(int argc, const char** argv){ if (argc != 6) { printf(".exe infile outfile out_width out_height rand_seed
"); return EXIT_FAILURE; } const char* infile = argv[1]; const char* outfile = argv[2]; const int width = atoi(argv[3]); const int height = atoi(argv[4]); const int rand_seed = atoi(argv[5]); srand(rand_seed); ZQ_DImage<float> in_img, out_img; if (!ZQ_ImageIO::loadImage(in_img, infile, 1)) { printf("failed to load %s
", infile); return EXIT_FAILURE; } int in_width = in_img.width(); int in_height = in_img.height(); int in_nChannels = in_img.nchannels(); out_img.allocate(width, height, in_nChannels); ZQ_GraphCutForTexture<float> sampler; if (!sampler.SetInputTexture(in_img.data(), in_width, in_height, in_nChannels)) { printf("failed to set input!
"); return EXIT_FAILURE; } if (!sampler.RandomSynthesis(width, height, 64)) { printf("failed to random synthesis!
"); return EXIT_FAILURE; } printf("random synthesis done!
"); if (!sampler.Optimize(1000)) { printf("failed to optimize!
"); return EXIT_FAILURE; } printf("optimize done!
"); if (!sampler.ExportOutputTexture(out_img.data())) { printf("failed to export!
"); return EXIT_FAILURE; } if (!ZQ_ImageIO::saveImage(out_img, outfile)) { printf("failed to save %s
", outfile); return EXIT_FAILURE; } printf("done! %s saved!
",outfile); return EXIT_SUCCESS;}

運行結果

輸入

輸出

二、基於優化的紋理合成

原理可以參考論文Texture Optimization for Example-based Synthesis, SIGGRAPH 2005

類定義在文件github.com/zuoqing1988/

提供兩種合成方法:

一種是不帶控制的合成方法,

一種是帶控制的合成方法(就是希望合成的結果與輸入的控制圖片整體分布接近)。

bool SynthesisWithoutControl(const int border_width, const float reduce_factor, const int max_level, const float grad_weight, const int to_max_iter, const int sor_iter, DImage& output);bool SynthesisWithControl(const DImage& ctrl, int border_width, const float reduce_factor, const int max_level, const float grad_weight, const float ctrl_weight, const int to_max_iter, const int sor_iter, DImage& output);

使用示例github.com/zuoqing1988/

#include "ZQ_TextureSynthesisProbe.h"#include "ZQ_TextureOptimization.h"#include "ZQ_DoubleImage.h"#include "ZQ_ImageIO.h"#include <time.h>using namespace ZQ;typedef ZQ_DImage<float> DImage;int main(){ const char* input_file = "input.jpg"; const char* ctrl_file = "ctrl.jpg"; const char* output_file1 = "to_no_ctrl.jpg"; const char* output_file = "to_ctrl.jpg"; DImage input,ctrl; if(!ZQ_ImageIO::loadImage(input,input_file,1)) { printf("failed to load image %s
",input_file); return EXIT_FAILURE; } if(!ZQ_ImageIO::loadImage(ctrl,ctrl_file,1)) { printf("failed to load image %s
",ctrl_file); return EXIT_FAILURE; } int nChannels = input.nchannels(); DImage output1(256,256,nChannels),output; ZQ_TextureOptimization to; to.SetSource(input); int borderWidth = 16; float reduce_factor = 0.5; int max_level = 6; float grad_weight = 0.07; float ctrl_weight = 0.03; int to_max_iter = 5; int sor_iter = 20; clock_t t1 = clock(); to.SynthesisWithoutControl(borderWidth,reduce_factor,max_level,grad_weight,to_max_iter,sor_iter,output1); clock_t t2 = clock(); to.SynthesisWithControl(ctrl,borderWidth,reduce_factor,max_level,grad_weight,ctrl_weight,to_max_iter,sor_iter,output); clock_t t3 = clock(); printf("%f %f
",0.001*(t2-t1),0.001*(t3-t2)); ZQ_ImageIO::saveImage(output1,output_file1); ZQ_ImageIO::saveImage(output,output_file); return EXIT_SUCCESS;}

運行結果

輸入:樣本

輸入:控制圖片

輸出:不帶控制的合成結果

輸出:帶控制的合成結果

推薦閱讀:

科普:崖柏手串各種紋理圖文詳解!
流年印記在臉上的是紋理,刻在心中的是永遠【情感驛站】
小葉紫檀手串不講究紋理,為何瘤疤葡萄瘤如此
黃蠟石各種紋理,終於集齊了!
畫畫用這種紋理排線簡直吊炸天!

TAG:紋理 | 計算機圖形學 |