1. 程式人生 > >基於L0範數平滑的影象漫畫特效生成演算法

基於L0範數平滑的影象漫畫特效生成演算法

void* ImageCartoonStylizationThread(void *arg)
{
	CartoonStylizationInfo *cartoonstylization_info = (CartoonStylizationInfo *)arg;
	BMPINFO *pSrcBitmap = cartoonstylization_info->pSrcBitmap;
	int block_count = cartoonstylization_info->block_count;

	int width = pSrcBitmap->lWidth;
	int height=  pSrcBitmap->lHeight;
	int size = width*height;
	int mem_size = size * sizeof(double);
	double *rdata = (double *)malloc(mem_size);
	double *gdata = (double *)malloc(mem_size);
	double *bdata = (double *)malloc(mem_size);

	// 資料轉換
	ConvertToDouble(pSrcBitmap, rdata, gdata, bdata);

	// 簡化細節
	double *rgb_data[3] = { rdata, gdata, bdata };
	L0ImageSmoothing(rgb_data, width, height, block_count, 0.01, 2.0);

	// 抽取邊緣
	rdata = rgb_data[0];
	gdata = rgb_data[1];
	bdata = rgb_data[2];
	double *gray_data = (double *)malloc(mem_size);
	double *hor_edgedata = (double *)malloc(mem_size);
	double *ver_edgedata = (double *)malloc(mem_size);
	for (int i = 0; i < size; i++)
	{
		gray_data[i] = (rdata[i]*0.299f + gdata[i]*0.587f + bdata[i]*0.114f);
	}
	EdgeDetectionFilter(gray_data, width, height, hor_edgedata, ver_edgedata);

	for (int i = 0; i < size; i++)
	{
		double edge_val = (fabs(hor_edgedata[i]) + fabs(ver_edgedata[i]))*1.2;
		edge_val = edge_val < 1.0 ? 1.0 - edge_val : 0.0;
		gray_data[i] = edge_val;
	}

	double *edge_data = (double *)malloc(mem_size);
	ExtractEdge(gray_data, edge_data, width, height, 15.7, 0.017, 75.5f);

	// 計算向量場
	double *vec_x = (double *)malloc(mem_size);
	double *vec_y = (double *)malloc(mem_size);
	CalcVectorField(gray_data, width, height, vec_x, vec_y, 1.0);

	// 線積分卷積
	LICFilter(edge_data, gray_data, vec_x, vec_y, width, height);

	free(vec_x);
	free(vec_y);
	vec_x = NULL;
	vec_y = NULL;
	free(edge_data);
	edge_data = NULL;

	// 結果合成
	for (int i = 0; i < size; i++)
	{
		rdata[i] *= gray_data[i];
		gdata[i] *= gray_data[i];
		bdata[i] *= gray_data[i];
	}

	// 資料轉換
	ConvertToUchar(rdata, gdata, bdata, pSrcBitmap);

	// 效果微調
	ImageAdjust(pSrcBitmap);

	free(gray_data);
	free(hor_edgedata);
	free(ver_edgedata);
	gray_data = NULL;
	hor_edgedata = NULL;
	ver_edgedata = NULL;

	free(rdata);
	free(gdata);
	free(bdata);
	rdata = NULL;
	gdata = NULL;
	bdata = NULL;

	return NULL;
}