I call this algorithm the poor man's segmentation. It should be made known that there is noise (JPEG artifacts) in the input images, but the code overcomes that, and works as requested. In the future, please save some time and grief by using PNG files! If you find this answer to be useful, please mark it as correct and upvote it. Thank you. :)
The output is:
The code is given below. In the function call threshold(frame_a, frame_a,
127, 255, THRESH_BINARY);
, the 127 value can be altered to suit one's taste:
#pragma comment(lib, "opencv_world340.lib")
#include <opencv2/opencv.hpp>
using namespace cv;
#include <iostream>
using namespace std;
int main(void)
{
Mat frame_a = imread("frame_a.jpg", CV_LOAD_IMAGE_GRAYSCALE);
Mat frame_b = imread("frame_b.jpg", CV_LOAD_IMAGE_GRAYSCALE);
if (frame_a.empty() || frame_b.empty())
{
cout << "Could not read input files" << endl;
return 1;
}
// get rid of JPEG artifacts.
// please use PNG next time!!!
threshold(frame_a, frame_a, 127, 255, THRESH_BINARY);
int fill_colour = 19;
for (int j = 0; j < frame_b.rows; j++)
{
for (int i = 0; i < frame_b.cols; i++)
{
unsigned char colour = frame_b.at<unsigned char>(j, i);
if (colour == 255)
floodFill(frame_a, Point(i, j), Scalar(fill_colour));
}
}
Mat frame_out(frame_a.rows, frame_a.cols, CV_8UC1);
for (int j = 0; j < frame_a.rows; j++)
{
for (int i = 0; i < frame_a.cols; i++)
{
unsigned char colour = frame_a.at<unsigned char>(j, i);
if (colour == fill_colour)
frame_out.at<unsigned char>(j, i) = 255;
else
frame_out.at<unsigned char>(j, i) = 0;
}
}
//imshow("frame a", frame_a);
//imshow("frame b", frame_b);
imshow("frame out", frame_out);
waitKey(0);
return 0;
}