真实感图像渲染系列:渲染可视化

这是真实感图像渲染系列的第六篇文章。

动机

一幅图片渲染时间少则一分钟,多则半天,等到渲染完成再看效果未免也太佛系了。况且诸如PPM算法亮度调节什么的一般在前两轮的时候,就已经大概知道了,并不需要渲染完。因此我们希望写一个实时显示渲染效果的类。

实现

显示部分在技术上没有任何难度,就是OpenCV中的imshow而已,如果必要,每次imshow之前,使用imwrite备份图片到文件。

我们需要一边显示一遍渲染,这个就需要多线程了。由于opencv的限制,imshow和waitKey只能在主线程调用,因此我们把图像渲染放在子线程里面去。这里线程的创建我使用了pthreads库。

具体细节就看代码啦。init函数传入一个Color类数组的指针,而PaintBoard能够实时监测该指针指向内容的变化,并且显示出来。(需要用户在窗口按回车键刷新)

 

#ifndef PAINT_BOARD_H
#define PAINT_BOARD_H
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

#include "../core/color.h"
using namespace std;

class PaintBoard {
	private:
		cv::Mat *image;
		Color **board;
		int sizX,sizY;
	public:
		PaintBoard();
		~PaintBoard();
		void init(int sizX,int sizY,Color** _board);
		void update();
		void display();
		void save();
		void save_raw();
};

#endif
#include "paint_board.h"
#include "glog/logging.h"
#include <iostream>
using namespace cv;

PaintBoard::PaintBoard() {
	sizX = -1,sizY = -1;
	image = NULL;
}
PaintBoard::~PaintBoard() {
}

void PaintBoard::init(int sizX,int sizY,Color** _board) {
	this->sizX = sizX;
	this->sizY = sizY;
	image = new Mat(this->sizX,this->sizY,CV_64FC3,Scalar(1.0,1.0,1.0));
	board = _board;
}

void PaintBoard::update() {
	assert(image);
	for (int i=0;i<sizX;i++) {
		for (int j=0;j<sizY;j++) {
			//Color& c = (*board)[(sizX-i-1)*sizY+j];
			Color& c = (*board)[i*sizY+j];
			Vec3f v(c.getR(),c.getG(),c.getB());
			image->at<Vec3d>(i,j) = v;
		}
	}
}
void PaintBoard::display() {
	imshow("picture", *image);
	waitKey(0);
}
void PaintBoard::save_raw() {
    FILE* fout = fopen("result.ppm","w");
    fprintf(fout,"P3 %d %d\n",sizY,sizX);
    fprintf(fout,"255\n");
    for (int i=0;i<sizX;i++)
    {
        for (int j=0;j<sizY;j++)
        {
			Color c = (*board)[i*sizY+j]*255;
            fprintf(fout,"% 3d % 3d % 3d",int(c.getR()),int(c.getG()),int(c.getB()));
        }
        fprintf(fout,"\n");
    }
    fclose(fout);
}
void PaintBoard::save() {
    vector<int>compression_params;
    compression_params.push_back(IMWRITE_PNG_COMPRESSION);
    compression_params.push_back(9);
    imwrite("result.bmp", (*image)*255);
}
#include <iostream>
#include "display/paint_board.h"
#include "json/json.h"
#include "render/raytracing.h"
#include "render/progressive_photon_mapping.h"
#include <unistd.h>
#include <fstream>
#include <pthread.h>

bool show_graph_flag = true;

void* show_graph(void* params) {
	Render *PPM = (Render*)params;
	PPM->run();
	show_graph_flag = false;
	return NULL;
}


int main(int argc, char** args)
{
	std::ifstream ifs("configures/config.json");
	Json::CharReaderBuilder reader;
	Json::Value root;
	JSONCPP_STRING errs;
	Json::parseFromStream(reader, ifs, &root, &errs);

	Render *PPM = new ProgressivePhotonMapping();
	//Render *PPM = new RayTracing();
	PaintBoard PB;
	PPM->accept(root);
	PPM->registerPaintBoard(&PB);

	pthread_t watcher;
	pthread_create(&watcher,NULL,show_graph,PPM);

	while (show_graph_flag) {
		PB.update();
		PB.save();
		PB.display();
		usleep(100000);
	}

	show_graph_flag = false;
	pthread_join(watcher,NULL);

	PB.update();
	PB.save();
}

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据