图像修复-TV修复模型
原理:
C++代码(灰度图像):
#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 TV_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; cv::namedWindow("1", cv::WINDOW_AUTOSIZE); cv::namedWindow("2", cv::WINDOW_AUTOSIZE); cv::namedWindow("3", cv::WINDOW_AUTOSIZE); cv::Mat image_array = cv::imread("CDD.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); cv::Mat mask_array = cv::imread("1.png"); std::vector<Coord> mask_data = create_mask(mask_array); /* TV_GRAY PDE Inpainting. */ int total_iters[] = { 500 }; int total_stages = 2; float lambdas[] = { 0.2 }; float as[] = { 0.5 }; double t = getTickCount();//当前滴答数 TV_GRAY(image_array, mask_data, output_array,total_iters, total_stages,lambdas, as); 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); cv::imshow("2", mask_array); cv::imshow("3", output_array); cv::waitKey(0); } void TV_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(); 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 Hon, Hoe, How, Hos; float Hoo; 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); Hon = Wn / (Wn + We + Ww + Ws + lambda); Hoe = We / (Wn + We + Ww + Ws + lambda); How = Ww / (Wn + We + Ww + Ws + lambda); Hos = Ws / (Wn + We + Ww + Ws + lambda); Hoo = lambda / (Wn + We + Ww + Ws + lambda); input_array.at<float>(row, col) = (Hon * UN + Hoe * UE + How * UW + Hos * US + Hoo * UO); 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) { //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图像):
#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 TV_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; 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("CDD2.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); /* Load the mask and fill the vector*/ cv::Mat mask_array = cv::imread("1.png"); std::vector<Coord> mask_data = create_mask(mask_array); /* TV RGB PDE Inpainting. */ int total_iters[] = { 500 }; int total_stages = 2; float lambdas[] = { 0.2 }; float as[] = { 0.5 }; double t = getTickCount();//当前滴答数 TV_RGB(image_array, mask_data, output_array,total_iters, total_stages,lambdas, as); t = ((double)getTickCount() - t) / getTickFrequency(); printf("算法用时:%f秒\n", t); /* Display the output */ cv::normalize(output_array, output_array, 0, 255.0, cv::NORM_MINMAX, CV_8UC3); output_array.convertTo(output_array, CV_8UC3); imwrite("200.png", output_array); cv::imshow("2", mask_array); cv::imshow("3", output_array); cv::waitKey(0); } void TV_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计算TV for (int stage = 0; stage < total_stages; stage++) { 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 Hon1, Hon2, Hon3; float Hoe1, Hoe2, Hoe3; float How1, How2, How3; float Hos1, Hos2, Hos3; float Hoo1, Hoo2, Hoo3; //算法运行 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]; UO2 = input_array.at<cv::Vec3f>(row, col)[1]; UO3 = input_array.at<cv::Vec3f>(row, col)[2]; UW1 = input_array.at<cv::Vec3f>(row - 1, col)[0]; UW2 = input_array.at<cv::Vec3f>(row - 1, col)[1]; UW3 = input_array.at<cv::Vec3f>(row - 1, col)[2]; UE1 = input_array.at<cv::Vec3f>(row + 1, col)[0]; UE2 = input_array.at<cv::Vec3f>(row + 1, col)[1]; UE3 = input_array.at<cv::Vec3f>(row + 1, col)[2]; UN1 = input_array.at<cv::Vec3f>(row, col + 1)[0]; UN2 = input_array.at<cv::Vec3f>(row, col + 1)[1]; UN3 = input_array.at<cv::Vec3f>(row, col + 1)[2]; US1 = input_array.at<cv::Vec3f>(row, col - 1)[0]; US2 = input_array.at<cv::Vec3f>(row, col - 1)[1]; US3 = input_array.at<cv::Vec3f>(row, col - 1)[2]; UNW1 = input_array.at<cv::Vec3f>(row - 1, col + 1)[0]; UNW2 = input_array.at<cv::Vec3f>(row - 1, col + 1)[1]; UNW3 = input_array.at<cv::Vec3f>(row - 1, col + 1)[2]; USW1 = input_array.at<cv::Vec3f>(row - 1, col - 1)[0]; USW2 = input_array.at<cv::Vec3f>(row - 1, col - 1)[1]; USW3 = input_array.at<cv::Vec3f>(row - 1, col - 1)[2]; UNE1 = input_array.at<cv::Vec3f>(row + 1, col + 1)[0]; UNE2 = input_array.at<cv::Vec3f>(row + 1, col + 1)[1]; UNE3 = input_array.at<cv::Vec3f>(row + 1, col + 1)[2]; USE1 = input_array.at<cv::Vec3f>(row + 1, col - 1)[0]; USE2 = input_array.at<cv::Vec3f>(row + 1, col - 1)[1]; 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); Hon1 = Wn1 / (Wn1 + We1 + Ww1 + Ws1 + lambda); Hoe1 = We1 / (Wn1 + We1 + Ww1 + Ws1 + lambda); How1 = Ww1 / (Wn1 + We1 + Ww1 + Ws1 + lambda); Hos1 = Ws1 / (Wn1 + We1 + Ww1 + Ws1 + lambda); Hon2 = Wn2 / (Wn2 + We2 + Ww2 + Ws2 + lambda); Hoe2 = We2 / (Wn2 + We2 + Ww2 + Ws2 + lambda); How2 = Ww2 / (Wn2 + We2 + Ww2 + Ws2 + lambda); Hos2 = Ws2 / (Wn2 + We2 + Ww2 + Ws2 + lambda); Hon3 = Wn3 / (Wn3 + We3 + Ww3 + Ws3 + lambda); Hoe3 = We3 / (Wn3 + We3 + Ww3 + Ws3 + lambda); How3 = Ww3 / (Wn3 + We3 + Ww3 + Ws3 + lambda); Hos3 = Ws3 / (Wn3 + We3 + Ww3 + Ws3 + lambda); Hoo1 = lambda / (Wn1 + We1 + Ww1 + Ws1 + lambda); Hoo2 = lambda / (Wn2 + We2 + Ww2 + Ws2 + lambda); Hoo3 = lambda / (Wn3 + We3 + Ww3 + Ws3 + lambda); input_array.at<cv::Vec3f>(row, col)[0] = (Hon1 * UN1 + Hoe1 * UE1 + How1 * UW1 + Hos1 * US1 + Hoo1 * UO1); input_array.at<cv::Vec3f>(row, col)[1] = (Hon2 * UN2 + Hoe2 * UE2 + How2 * UW2 + Hos2 * US2 + Hoo2 * UO2); input_array.at<cv::Vec3f>(row, col)[2] = (Hon3 * UN3 + Hoe3 * UE3 + How3 * UW3 + Hos3 * US3 + Hoo3 * UO3); output_array.at<cv::Vec3f>(row, col)[0] = input_array.at<cv::Vec3f>(row, col)[0]; output_array.at<cv::Vec3f>(row, col)[1] = input_array.at<cv::Vec3f>(row, col)[1]; 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) { //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; }
测试图像:
转载请注明出处,欢迎讨论和交流!