This demonstration illustrates the implemantation of image restoration through inpainting algortihms using the OpenCV library. The application enables interactive masking of image regions follwoed by automated reconstruction of those areas using surrounding pixel data.
The program workflow involves loading a source image, allowing users to draw on it to define damaged regions, and then applying inpainting algorithms to seamlessly reconstruct the marked areas. The restoration process utilizes sophisticated interpolation techniques to blend the repaired sections with the existing image content.
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/photo.hpp"
#include <iostream>
using namespace cv;
using namespace std;
static void displayInstructions(char** args)
{
cout << "\nInteractive image restoration demonstration. The inpainting technique fills selected regions\n"
<< "by propagating information from neighboring pixels.\n"
"OpenCV version: " << CV_VERSION << "\n"
"Execution: " << args[0] << " [image_file -- defaults to fruits.jpg]\n" << endl;
cout << "Control keys: \n"
"\tESC - terminate application\n"
"\tr - reset to original image state\n"
"\ti or SPACE - execute restoration process\n"
"\t\t(prior to execution, mark regions on the image)\n" << endl;
}
Mat sourceImage, maskLayer;
Point previousPosition(-1, -1);
static void handleMouseEvents(int eventType, int posX, int posY, int mouseFlags, void*)
{
if(eventType == EVENT_LBUTTONUP || !(mouseFlags & EVENT_FLAG_LBUTTON))
previousPosition = Point(-1, -1);
else if(eventType == EVENT_LBUTTONDOWN)
previousPosition = Point(posX, posY);
else if(eventType == EVENT_MOUSEMOVE && (mouseFlags & EVENT_FLAG_LBUTTON))
{
Point currentPoint(posX, posY);
if(previousPosition.x < 0)
previousPosition = currentPoint;
line(maskLayer, previousPosition, currentPoint, Scalar(255, 255, 255), 5, 8, 0);
line(sourceImage, previousPosition, currentPoint, Scalar(255, 255, 255), 5, 8, 0);
previousPosition = currentPoint;
imshow("source", sourceImage);
}
}
int main(int argCount, char** argValues)
{
cv::CommandLineParser arguments(argCount, argValues, "{@input_image|fruits.jpg|}");
displayInstructions(argValues);
string filePath = samples::findFile(arguments.get<string>("@input_image"));
Mat initialImage = imread(filePath, IMREAD_COLOR);
if(initialImage.empty())
{
cout << "Failed to load image: " << filePath << ". Correct usage: inpaint <image_path>\n" << endl;
return -1;
}
namedWindow("source", WINDOW_AUTOSIZE);
sourceImage = initialImage.clone();
maskLayer = Mat::zeros(sourceImage.size(), CV_8UC1);
imshow("source", sourceImage);
setMouseCallback("source", handleMouseEvents, nullptr);
for(;;)
{
char keyPress = (char)waitKey();
if(keyPress == 27)
break;
if(keyPress == 'r')
{
maskLayer = Scalar(0);
initialImage.copyTo(sourceImage);
imshow("source", sourceImage);
}
if(keyPress == 'i' || keyPress == ' ')
{
Mat reconstructed;
inpaint(sourceImage, maskLayer, reconstructed, 3, INPAINT_TELEA);
imshow("restored_output", reconstructed);
}
}
return 0;
}
The core restoration functionality is executed through the inpaint() function call, which processes the source image along with the defined mask to generate a seamlessly reconstructed output.
inpaint(sourceImage, maskLayer, reconstructed, 3, INPAINT_TELEA);