图像修复-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;
}
测试图像:










转载请注明出处,欢迎讨论和交流!

浙公网安备 33010602011771号