图像修复-T-P模型
原理:









C++代码(灰度图像):
//TP Inpaint
#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);
void TP_GRAY(
cv::Mat& input_array, std::vector<Coord>& mask_array, cv::Mat& output_array,
int* total_iters, int total_stages, float* lambdas, float* as);
int main(int argc, char* argv[])
{
cv::Mat output_array;
/* 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("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);
cv::imshow("1", image_array);
/* 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);
/*
TP PDE Inpainting.
*/
int total_iters[] = { 500 };
int total_stages = 2;
float lambdas[] = { 0.2 };
float as[] = { 0.5 };
TP_GRAY(image_array, mask_data, output_array, total_iters, total_stages, lambdas, as);
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("2", mask_array);
cv::imshow("3", output_array);
cv::waitKey(0);
}
void TP_GRAY(
cv::Mat& input_array, std::vector<Coord>& mask_array, cv::Mat& output_array,
int* total_iters, int total_stages, float* lambdas, float* as)
{
typedef unsigned char logical_type;
//初始化输出图像
input_array.copyTo(output_array);
//掩模图像的大小
int size_mask = mask_array.size();
//在每个stage计算TP
for (int stage = 0; stage < total_stages; stage++)
{
int total_iter = total_iters[stage];
float lambda = lambdas[stage];
float a = as[stage];
float UO, UN, UW, US, UE, UNE, UNW, USW, USE;
float Un, Ue, Uw, Us;
float Wn, We, Ww, Ws;
float K, bot;
//算法运行
for (int iter = 0; iter < total_iter; iter++)
{
for (int cont = 0; cont < size_mask; cont++)
{
Coord coord = mask_array.at(cont);
int row = coord.i;
int col = coord.j;
UO = input_array.at<float>(row, col);
UW = input_array.at<float>(row - 1, col);
UE = input_array.at<float>(row + 1, col);
UN = input_array.at<float>(row, col + 1);
US = input_array.at<float>(row, col - 1);
UNW = input_array.at<float>(row - 1, col + 1);
USW = input_array.at<float>(row - 1, col - 1);
UNE = input_array.at<float>(row + 1, col + 1);
USE = input_array.at<float>(row + 1, col - 1);
Un = sqrt((UO - UN) * (UO - UN) + ((UNW - UNE) / 2.0) * ((UNW - UNE) / 2.0));
Ue = sqrt((UO - UE) * (UO - UE) + ((UNE - USE) / 2.0) * ((UNE - USE) / 2.0));
Uw = sqrt((UO - UW) * (UO - UW) + ((UNW - USW) / 2.0) * ((UNW - USW) / 2.0));
Us = sqrt((UO - US) * (UO - US) + ((USW - USE) / 2.0) * ((USW - USE) / 2.0));
Wn = 1.0 / sqrt(Un * Un + a * a);
We = 1.0 / sqrt(Ue * Ue + a * a);
Ww = 1.0 / sqrt(Uw * Uw + a * a);
Ws = 1.0 / sqrt(Us * Us + a * a);
K = 1.0 - 1.0 / (1.0 + Un * Un + Ue * Ue + Uw * Uw + Us * Us);
bot = 2.0 * (1.0 - K) + K * (Wn + We + Ww + Ws) + lambda;
input_array.at<float>(row, col) = K * (Wn * UN + We * UE + Ww * UW + Ws * US) / bot + ((1.0 - K) / 2.0) * (UN + UE + UW + US) / bot + lambda * UO / bot;
output_array.at<float>(row, col) = input_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)
{
Coord xy;
xy.i = i;
xy.j = j;
xy.color = PIXEL_WHITE;
mask_data.push_back(xy);
}
}
}
return mask_data;
}
C++代码(RGB图像):
//TP Inpaint
#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);
void TP_RGB(
cv::Mat& input_array, std::vector<Coord>& mask_array, cv::Mat& output_array,
int* total_iters, int total_stages, float* lambdas, float* as);
int main(int argc, char* argv[])
{
cv::Mat output_array;
/* 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("lena.png");
image_array.convertTo(image_array, CV_32FC3);
cv::normalize(image_array, image_array, 0, 1, cv::NORM_MINMAX, CV_32FC3);
cv::imshow("1", image_array);
/* 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);
/*
TP PDE Inpainting.
*/
int total_iters[] = { 500 };
int total_stages = 2;
float lambdas[] = { 0.2 };
float as[] = { 0.2 };
TP_RGB(image_array, mask_data, output_array, total_iters, total_stages, lambdas, as);
cv::normalize(output_array, output_array, 0, 255.0, cv::NORM_MINMAX, CV_8UC3);
output_array.convertTo(output_array, CV_8UC3);
/* Display the output */
cv::imshow("2", mask_array);
cv::imshow("3", output_array);
cv::waitKey(0);
}
void TP_RGB(
cv::Mat& input_array, std::vector<Coord>& mask_array, cv::Mat& output_array,
int* total_iters, int total_stages, float* lambdas, float* as)
{
typedef unsigned char logical_type;
//初始化输出图像
input_array.copyTo(output_array);
//掩模图像的大小
int size_mask = mask_array.size();
//在每个stage计算TP
for (int stage = 0; stage < total_stages; stage++)
{
/* Grab data */
int total_iter = total_iters[stage];
float lambda = lambdas[stage];
float a = as[stage];
float UO1, UO2, UO3;
float UN1, UN2, UN3;
float UW1, UW2, UW3;
float US1, US2, US3;
float UE1, UE2, UE3;
float UNE1, UNE2, UNE3;
float UNW1, UNW2, UNW3;
float USW1, USW2, USW3;
float USE1, USE2, USE3;
float Un1, Un2, Un3;
float Ue1, Ue2, Ue3;
float Uw1, Uw2, Uw3;
float Us1, Us2, Us3;
float Wn1, Wn2, Wn3;
float We1, We2, We3;
float Ww1, Ww2, Ww3;
float Ws1, Ws2, Ws3;
float K1, bot1;
float K2, bot2;
float K3, bot3;
//算法运行
for (int iter = 0; iter < total_iter; iter++)
{
for (int cont = 0; cont < size_mask; cont++)
{
Coord coord = mask_array.at(cont);
int row = coord.i;
int col = coord.j;
UO1 = input_array.at<cv::Vec3f>(row, col)[0];
UW1 = input_array.at<cv::Vec3f>(row - 1, col)[0];
UE1 = input_array.at<cv::Vec3f>(row + 1, col)[0];
UN1 = input_array.at<cv::Vec3f>(row, col + 1)[0];
US1 = input_array.at<cv::Vec3f>(row, col - 1)[0];
UNW1 = input_array.at<cv::Vec3f>(row - 1, col + 1)[0];
USW1 = input_array.at<cv::Vec3f>(row - 1, col - 1)[0];
UNE1 = input_array.at<cv::Vec3f>(row + 1, col + 1)[0];
USE1 = input_array.at<cv::Vec3f>(row + 1, col - 1)[0];
UO2 = input_array.at<cv::Vec3f>(row, col)[1];
UW2 = input_array.at<cv::Vec3f>(row - 1, col)[1];
UE2 = input_array.at<cv::Vec3f>(row + 1, col)[1];
UN2 = input_array.at<cv::Vec3f>(row, col + 1)[1];
US2 = input_array.at<cv::Vec3f>(row, col - 1)[1];
UNW2 = input_array.at<cv::Vec3f>(row - 1, col + 1)[1];
USW2 = input_array.at<cv::Vec3f>(row - 1, col - 1)[1];
UNE2 = input_array.at<cv::Vec3f>(row + 1, col + 1)[1];
USE2 = input_array.at<cv::Vec3f>(row + 1, col - 1)[1];
UO3 = input_array.at<cv::Vec3f>(row, col)[2];
UW3 = input_array.at<cv::Vec3f>(row - 1, col)[2];
UE3 = input_array.at<cv::Vec3f>(row + 1, col)[2];
UN3 = input_array.at<cv::Vec3f>(row, col + 1)[2];
US3 = input_array.at<cv::Vec3f>(row, col - 1)[2];
UNW3 = input_array.at<cv::Vec3f>(row - 1, col + 1)[2];
USW3 = input_array.at<cv::Vec3f>(row - 1, col - 1)[2];
UNE3 = input_array.at<cv::Vec3f>(row + 1, col + 1)[2];
USE3 = input_array.at<cv::Vec3f>(row + 1, col - 1)[2];
Un1 = sqrt((UO1 - UN1) * (UO1 - UN1) + ((UNW1 - UNE1) / 2.0) * ((UNW1 - UNE1) / 2.0));
Ue1 = sqrt((UO1 - UE1) * (UO1 - UE1) + ((UNE1 - USE1) / 2.0) * ((UNE1 - USE1) / 2.0));
Uw1 = sqrt((UO1 - UW1) * (UO1 - UW1) + ((UNW1 - USW1) / 2.0) * ((UNW1 - USW1) / 2.0));
Us1 = sqrt((UO1 - US1) * (UO1 - US1) + ((USW1 - USE1) / 2.0) * ((USW1 - USE1) / 2.0));
Un2 = sqrt((UO2 - UN2) * (UO2 - UN2) + ((UNW2 - UNE2) / 2.0) * ((UNW2 - UNE2) / 2.0));
Ue2 = sqrt((UO2 - UE2) * (UO2 - UE2) + ((UNE2 - USE2) / 2.0) * ((UNE2 - USE2) / 2.0));
Uw2 = sqrt((UO2 - UW2) * (UO2 - UW2) + ((UNW2 - USW2) / 2.0) * ((UNW2 - USW2) / 2.0));
Us2 = sqrt((UO2 - US2) * (UO2 - US2) + ((USW2 - USE2) / 2.0) * ((USW2 - USE2) / 2.0));
Un3 = sqrt((UO3 - UN3) * (UO3 - UN3) + ((UNW3 - UNE3) / 2.0) * ((UNW3 - UNE3) / 2.0));
Ue3 = sqrt((UO3 - UE3) * (UO3 - UE3) + ((UNE3 - USE3) / 2.0) * ((UNE3 - USE3) / 2.0));
Uw3 = sqrt((UO3 - UW3) * (UO3 - UW3) + ((UNW3 - USW3) / 2.0) * ((UNW3 - USW3) / 2.0));
Us3 = sqrt((UO3 - US3) * (UO3 - US3) + ((USW3 - USE3) / 2.0) * ((USW3 - USE3) / 2.0));
Wn1 = 1.0 / sqrt(Un1 * Un1 + a * a);
We1 = 1.0 / sqrt(Ue1 * Ue1 + a * a);
Ww1 = 1.0 / sqrt(Uw1 * Uw1 + a * a);
Ws1 = 1.0 / sqrt(Us1 * Us1 + a * a);
Wn2 = 1.0 / sqrt(Un2 * Un2 + a * a);
We2 = 1.0 / sqrt(Ue2 * Ue2 + a * a);
Ww2 = 1.0 / sqrt(Uw2 * Uw2 + a * a);
Ws2 = 1.0 / sqrt(Us2 * Us2 + a * a);
Wn3 = 1.0 / sqrt(Un3 * Un3 + a * a);
We3 = 1.0 / sqrt(Ue3 * Ue3 + a * a);
Ww3 = 1.0 / sqrt(Uw3 * Uw3 + a * a);
Ws3 = 1.0 / sqrt(Us3 * Us3 + a * a);
K1 = 1.0 - 1.0 / (1.0 + Un1 * Un1 + Ue1 * Ue1 + Uw1 * Uw1 + Us1 * Us1);
K2 = 1.0 - 1.0 / (1.0 + Un2 * Un2 + Ue2 * Ue2 + Uw2 * Uw2 + Us2 * Us2);
K3 = 1.0 - 1.0 / (1.0 + Un3 * Un3 + Ue3 * Ue3 + Uw3 * Uw3 + Us3 * Us3);
bot1 = 2.0 * (1.0 - K1) + K1 * (Wn1 + We1 + Ww1 + Ws1) + lambda;
bot2 = 2.0 * (1.0 - K2) + K2 * (Wn2 + We2 + Ww2 + Ws2) + lambda;
bot3 = 2.0 * (1.0 - K3) + K3 * (Wn3 + We3 + Ww3 + Ws3) + lambda;
input_array.at<cv::Vec3f>(row, col)[0] = K1 * (Wn1 * UN1 + We1 * UE1 + Ww1 * UW1 + Ws1 * US1) / bot1 + ((1.0 - K1) / 2.0) * (UN1 + UE1 + UW1 + US1) / bot1 + lambda * UO1 / bot1;
output_array.at<cv::Vec3f>(row, col)[0] = input_array.at<cv::Vec3f>(row, col)[0];
input_array.at<cv::Vec3f>(row, col)[1] = K2 * (Wn2 * UN2 + We2 * UE2 + Ww2 * UW2 + Ws2 * US2) / bot2 + ((1.0 - K2) / 2.0) * (UN2 + UE2 + UW2 + US2) / bot2 + lambda * UO2 / bot2;
output_array.at<cv::Vec3f>(row, col)[1] = input_array.at<cv::Vec3f>(row, col)[1];
input_array.at<cv::Vec3f>(row, col)[2] = K3 * (Wn3 * UN3 + We3 * UE3 + Ww3 * UW3 + Ws3 * US3) / bot3 + ((1.0 - K3) / 2.0) * (UN3 + UE3 + UW3 + US3) / bot3 + lambda * UO3 / bot3;
output_array.at<cv::Vec3f>(row, col)[2] = input_array.at<cv::Vec3f>(row, col)[2];
}
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)
{
Coord xy;
xy.i = i;
xy.j = j;
xy.color = PIXEL_WHITE;
mask_data.push_back(xy);
}
}
}
return mask_data;
}
测试图像:










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

浙公网安备 33010602011771号