图像修复-BSCB修复模型

原理:

 

 

C++代码(灰度图像):

//#define OPENCV_TRAITS_ENABLE_DEPRECATED
#include <iostream>
#include <stdlib.h>
#include <math.h>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <time.h>

using namespace cv;
using namespace std;

enum { PIXEL_WHITE = 1};
typedef struct coord 
{
	int i;
	int j;
	int color;
}Coord;

std::vector<Coord> create_mask(cv::Mat& mask);

//BSCB模型 
void BSCB_GRAY(
	cv::Mat& input_array, std::vector<Coord>& mask_array, cv::Mat& output_array,
	int* total_iters, int* total_inpaint_iters, int* total_anidiffuse_iters, int total_stages,
	float* delta_ts, float* sensitivities, int diffuse_coef);

int main(int argc, char* argv[])
{
	cv::Mat output_array;

	/* Load and normalize the image */
	cv::Mat image_array = cv::imread("lena.png");
	image_array.convertTo(image_array, CV_32FC1);
	cv::cvtColor(image_array, image_array, cv::COLOR_BGR2GRAY);
	cv::normalize(image_array, image_array, 0, 1, cv::NORM_MINMAX, CV_32FC1);


	/* Load the mask and fill the vector*/
	cv::Mat mask_array = cv::imread("lena_mask.png");
	std::vector<Coord> mask_data = create_mask(mask_array);


	/* Create the windows */
	cv::namedWindow("1", cv::WINDOW_AUTOSIZE);
	cv::namedWindow("2", cv::WINDOW_AUTOSIZE);
	cv::namedWindow("3", cv::WINDOW_AUTOSIZE);

	/*
		Bertalmio PDE Inpainting.
	*/
	int total_iters[] = { 200 };
	int total_inpaint_iters[] = { 6 };
	int total_anidiffuse_iters[] = { 6 };
	int total_stages = 2;
	float delta_ts[] = { 0.02f };
	float sensitivites[] = { 100 };
	int diffuse_coef = 1;
	double t = getTickCount();//当前滴答数

	BSCB_GRAY(
		image_array, mask_data, output_array,
		total_iters, total_inpaint_iters, total_anidiffuse_iters, total_stages,
		delta_ts, sensitivites, diffuse_coef);

	t = ((double)getTickCount() - t) / getTickFrequency();
	printf("算法用时:%f秒\n", t);

	cv::normalize(output_array, output_array, 0, 255.0, cv::NORM_MINMAX, CV_8UC1);
	output_array.convertTo(output_array, CV_8UC1);

	/* Display the output */
	cv::imshow("1", image_array);
	cv::imshow("2", mask_array);
	cv::imshow("3", output_array);
	cv::waitKey(0);
}

void BSCB_GRAY(
	cv::Mat& input_array, std::vector<Coord>& mask_array, cv::Mat& output_array,
	int* total_iters, int* total_inpaint_iters, int* total_anidiffuse_iters, int total_stages,
	float* delta_ts, float* sensitivities, int diffuse_coef) 
{
	typedef unsigned char logical_type;

	cv::Mat image_grad_row;
	cv::Mat image_grad_col;
	cv::Mat image_grad_norm;
	cv::Mat image_iso_row;
	cv::Mat image_iso_col;
	cv::Mat image_iso_norm;
	cv::Mat image_laplacian;
	cv::Mat image_laplacian_grad_row;
	cv::Mat image_laplacian_grad_col;
	cv::Mat diffuse_coefs;
	cv::Mat temp;

	//初始化输出图像
	input_array.copyTo(output_array);
	//掩模图像的大小
	int size_mask = mask_array.size();
	//在每个stage计算BSCB
	for (int stage = 0; stage < total_stages; stage++)
	{
		int total_iter = total_iters[stage];
		int total_inpaint_iter = total_inpaint_iters[stage];
		int total_anidiffuse_iter = total_anidiffuse_iters[stage];
		float sensitivity = sensitivities[stage];
		float delta_t = delta_ts[stage];

		//算法运行
		for (int iter = 0; iter < total_iter; iter++)
		{
			//执行各向异性扩散
			for (int iter_aniffuse = 0; iter_aniffuse < total_anidiffuse_iter; iter_aniffuse++)
			{
				cv::Sobel(output_array, image_grad_row, -1, 0, 1);
				cv::Sobel(output_array, image_grad_col, -1, 1, 0);
				cv::magnitude(image_grad_row, image_grad_col, image_grad_norm);
				if (diffuse_coef == 0)
				{
					cv::exp(-(image_grad_norm.mul(1 / sensitivity)), diffuse_coefs);
				}
				else
				{
					cv::pow(image_grad_norm.mul(1 / sensitivity), 2, temp);
					diffuse_coefs = 1 / (1 + temp);
				}
				cv::Laplacian(output_array, image_laplacian, -1);

				for (int cont = 0; cont < size_mask; cont++)
				{
					Coord coord = mask_array.at(cont);
					int row = coord.i;
					int col = coord.j;

					output_array.at<float>(row, col) +=
						delta_t * (diffuse_coefs.at<float>(row, col) * image_laplacian.at<float>(row, col));
				}
			}

			//算法运行
			for (int total_inpaint_iters = 0; total_inpaint_iters < total_inpaint_iter; total_inpaint_iters++)
			{
				cv::Sobel(output_array, image_iso_row, -1, 1, 0);
				cv::Sobel(output_array, image_iso_col, -1, 0, 1);
				image_iso_row *= -1;
				cv::sqrt(image_iso_row.mul(image_iso_row) + image_iso_col.mul(image_iso_col), image_iso_norm);
				cv::Laplacian(output_array, image_laplacian, -1);
				cv::Sobel(image_laplacian, image_laplacian_grad_row, -1, 0, 1);
				cv::Sobel(image_laplacian, image_laplacian_grad_col, -1, 1, 0);

				for (int cont = 0; cont < size_mask; cont++)
				{
					Coord coord = mask_array.at(cont);
					int row = coord.i;
					int col = coord.j;
					if (image_iso_norm.at<float>(row, col) != 0)
					{
						output_array.at<float>(row, col) -= delta_t * (
							image_iso_row.at<float>(row, col) * image_laplacian_grad_row.at<float>(row, col) +
							image_iso_col.at<float>(row, col) * image_laplacian_grad_col.at<float>(row, col)) /
							image_iso_norm.at<float>(row, col);
						output_array.at<float>(row, col) = (output_array.at<float>(row, col) > 1.0f ? 1 : output_array.at<float>(row, col));
						output_array.at<float>(row, col) = (output_array.at<float>(row, col) < 0.0f ? 0 : output_array.at<float>(row, col));
					}
				}
			}
			//printf("%d\n", iter);
		}
	}
}

/*
	Save the inpainting domain to dinamic vector
*/
std::vector<Coord> create_mask(cv::Mat& mask) {
	std::vector<Coord> mask_data;
	for (int i = 1; i < mask.rows - 1; i++) {
		for (int j = 1; j < mask.cols - 1; j++) {
			if (mask.at<cv::Vec3b>(i, j)[0] != 0) 
			{ //BLUE GREEN RED --> white (255,255,255) 
				Coord xy;
				xy.i = i;
				xy.j = j;
				xy.color = PIXEL_WHITE;
				mask_data.push_back(xy);
			}
		}
	}
	return mask_data;
}

C++代码(RGB图像):

//#define OPENCV_TRAITS_ENABLE_DEPRECATED
#include "opencv2/opencv.hpp";
#include <thread>  
#include <iostream>
#include <stdlib.h>
#include <math.h>
#include<vector>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <time.h>


using namespace std;
using namespace cv;

enum { PIXEL_WHITE = 1 };
typedef struct coord 
{
	int i;
	int j;
	int color;
}Coord;

std::vector<Coord> create_mask(cv::Mat& mask);

void BSCB_GRAY(
	cv::Mat& input_array, std::vector<Coord>& mask_array, cv::Mat& output_array,
	int* total_iters, int* total_inpaint_iters, int* total_anidiffuse_iters, int total_stages,
	float* delta_ts, float* sensitivities, int diffuse_coef);

int main(int argc, char* argv[])
{
	cv::Mat output_array;
	cv::Mat res(output_array.rows, output_array.cols, CV_32FC3); //用来存储目的图片的矩阵
	/* Create the windows */
	cv::namedWindow("1", cv::WINDOW_AUTOSIZE);
	cv::namedWindow("2", cv::WINDOW_AUTOSIZE);
	cv::namedWindow("3", cv::WINDOW_AUTOSIZE);

	/* Load and normalize the image */
	cv::Mat image_array = cv::imread("test.png");
	cv::imshow("1", image_array);
	image_array.convertTo(image_array, CV_32FC3);
	cv::normalize(image_array, image_array, 0, 1, cv::NORM_MINMAX, CV_32FC3);

	cv::Mat r(image_array.rows, image_array.cols, CV_32FC1);
	cv::Mat g(image_array.rows, image_array.cols, CV_32FC1);
	cv::Mat b(image_array.rows, image_array.cols, CV_32FC1);

	vector<Mat> out = { b,g,r };

	split(image_array, out);


	/* Load the mask and fill the vector*/
	cv::Mat mask_array = cv::imread("test_mask.png");
	std::vector<Coord> mask_data = create_mask(mask_array);

	/*
		Bertalmio PDE Inpainting.
	*/
	int total_iters[] = { 500 };
	int total_inpaint_iters[] = { 6 };
	int total_anidiffuse_iters[] = { 6 };
	int total_stages = 2;
	float delta_ts[] = { 0.02f };
	float sensitivites[] = { 100 };
	int diffuse_coef = 1;

	BSCB_GRAY(
		b, mask_data, b,
		total_iters, total_inpaint_iters, total_anidiffuse_iters, total_stages,
		delta_ts, sensitivites, diffuse_coef);
	BSCB_GRAY(
		g, mask_data, g,
		total_iters, total_inpaint_iters, total_anidiffuse_iters, total_stages,
		delta_ts, sensitivites, diffuse_coef);
	BSCB_GRAY(
		r, mask_data, r,
		total_iters, total_inpaint_iters, total_anidiffuse_iters, total_stages,
		delta_ts, sensitivites, diffuse_coef);

	merge(out, output_array);
	cv::normalize(output_array, output_array, 0, 255.0, cv::NORM_MINMAX, CV_8UC3);
	output_array.convertTo(output_array, CV_8UC3);
	
	imwrite("1.png", output_array);

	/* Display the output */
	cv::imshow("2", mask_array);
	cv::imshow("3", output_array);

	cv::waitKey(0);
}

void BSCB_GRAY(
	cv::Mat& input_array, std::vector<Coord>& mask_array, cv::Mat& output_array,
	int* total_iters, int* total_inpaint_iters, int* total_anidiffuse_iters, int total_stages,
	float* delta_ts, float* sensitivities, int diffuse_coef)
{
	typedef unsigned char logical_type;

	cv::Mat image_grad_row;
	cv::Mat image_grad_col;
	cv::Mat image_grad_norm;
	cv::Mat image_iso_row;
	cv::Mat image_iso_col;
	cv::Mat image_iso_norm;
	cv::Mat image_laplacian;
	cv::Mat image_laplacian_grad_row;
	cv::Mat image_laplacian_grad_col;
	cv::Mat diffuse_coefs;
	cv::Mat temp;

	//初始化输出图像
	input_array.copyTo(output_array);
	//掩模图像的大小
	int size_mask = mask_array.size();
	//在每个stage计算BSCB
	for (int stage = 0; stage < total_stages; stage++)
	{
		int total_iter = total_iters[stage];
		int total_inpaint_iter = total_inpaint_iters[stage];
		int total_anidiffuse_iter = total_anidiffuse_iters[stage];
		float sensitivity = sensitivities[stage];
		float delta_t = delta_ts[stage];

		//算法运行
		for (int iter = 0; iter < total_iter; iter++)
		{
			//执行各向异性扩散
			for (int iter_aniffuse = 0; iter_aniffuse < total_anidiffuse_iter; iter_aniffuse++)
			{
				cv::Sobel(output_array, image_grad_row, -1, 0, 1);
				cv::Sobel(output_array, image_grad_col, -1, 1, 0);
				cv::magnitude(image_grad_row, image_grad_col, image_grad_norm);
				if (diffuse_coef == 0)
				{
					cv::exp(-(image_grad_norm.mul(1 / sensitivity)), diffuse_coefs);
				}
				else
				{
					cv::pow(image_grad_norm.mul(1 / sensitivity), 2, temp);
					diffuse_coefs = 1 / (1 + temp);
				}
				cv::Laplacian(output_array, image_laplacian, -1);

				for (int cont = 0; cont < size_mask; cont++)
				{
					Coord coord = mask_array.at(cont);
					int row = coord.i;
					int col = coord.j;

					output_array.at<float>(row, col) +=
						delta_t * (diffuse_coefs.at<float>(row, col) * image_laplacian.at<float>(row, col));
				}
			}

			//算法运行
			for (int total_inpaint_iters = 0; total_inpaint_iters < total_inpaint_iter; total_inpaint_iters++)
			{
				cv::Sobel(output_array, image_iso_row, -1, 1, 0);
				cv::Sobel(output_array, image_iso_col, -1, 0, 1);
				image_iso_row *= -1;
				cv::sqrt(image_iso_row.mul(image_iso_row) + image_iso_col.mul(image_iso_col), image_iso_norm);
				cv::Laplacian(output_array, image_laplacian, -1);
				cv::Sobel(image_laplacian, image_laplacian_grad_row, -1, 0, 1);
				cv::Sobel(image_laplacian, image_laplacian_grad_col, -1, 1, 0);

				for (int cont = 0; cont < size_mask; cont++)
				{
					Coord coord = mask_array.at(cont);
					int row = coord.i;
					int col = coord.j;
					if (image_iso_norm.at<float>(row, col) != 0)
					{
						output_array.at<float>(row, col) -= delta_t * (
							image_iso_row.at<float>(row, col) * image_laplacian_grad_row.at<float>(row, col) +
							image_iso_col.at<float>(row, col) * image_laplacian_grad_col.at<float>(row, col)) /
							image_iso_norm.at<float>(row, col);
						output_array.at<float>(row, col) = (output_array.at<float>(row, col) > 1.0f ? 1 : output_array.at<float>(row, col));
						output_array.at<float>(row, col) = (output_array.at<float>(row, col) < 0.0f ? 0 : output_array.at<float>(row, col));
					}
				}
			}
			printf("%d\n", iter);
		}
	}
}

/*
	Save the inpainting domain to dinamic vector
*/
std::vector<Coord> create_mask(cv::Mat& mask) 
{
	std::vector<Coord> mask_data;
	for (int i = 1; i < mask.rows - 1; i++) 
	{
		for (int j = 1; j < mask.cols - 1; j++) 
		{
			if (mask.at<cv::Vec3b>(i, j)[0] != 0) 
			{ //BLUE GREEN RED --> white (255,255,255) 
				Coord xy;
				xy.i = i;
				xy.j = j;
				xy.color = PIXEL_WHITE;
				mask_data.push_back(xy);
			}
		}
	}
	return mask_data;
}

测试图像:

 

posted @ 2021-03-20 21:16  司砚章  阅读(564)  评论(0编辑  收藏  举报