Hello everyone,
When running grabCut on an the same input in the loop every time I will get the different output, but if I restart the program, the output, even though different within the loop, will match the result of corresponding iteration from the previous run. I know, that grabCut will use some singletons so that the instance will be there through all the runs until the program will be terminated, but still, why do the separate runs of the algorithm interfere with each other (somehow) and what to do to get around that? I would need some level of determinism when the algorithm is running. Should I then restart the program after every single run? Does not make much sense...
I checked it with the unit test. If on one run I will save the results to disk like this:
TEST(PreprocessingTests, CutAndFilterSave)
{
auto original_path = std::experimental::filesystem::current_path();
std::experimental::filesystem::current_path("../tests/data/");
std::string output_directory = "cutAndFilterPreviousRun";
std::experimental::filesystem::create_directory(output_directory);
cv::Mat hidden_mouth_image = cv::imread("hidden_mouth.png", cv::IMREAD_GRAYSCALE);
EXPECT_TRUE(hidden_mouth_image.data);
cv::Mat whole_face_image = cv::imread("whole_face.png", cv::IMREAD_GRAYSCALE);
EXPECT_TRUE(whole_face_image.data);
std::vector<cv::Mat> images_to_save;
images_to_save.emplace_back(hidden_mouth_image);
images_to_save.emplace_back(whole_face_image);
processImagesForComparison(images_to_save);
cv::imwrite(output_directory + "/hidden_mouth_filtered.png", images_to_save.at(0));
cv::imwrite(output_directory + "/whole_face_filtered.png", images_to_save.at(1));
std::experimental::filesystem::current_path(original_path);
}
And on second run I will run this function
TEST(PreprocessingTests, CutAndFilterRead)
{
auto original_path = std::experimental::filesystem::current_path();
std::experimental::filesystem::current_path("../tests/data/");
std::string output_directory = "cutAndFilterPreviousRun";
if (std::experimental::filesystem::exists(output_directory))
{
cv::Mat hidden_mouth_image_filtered = cv::imread(output_directory + "/hidden_mouth_filtered.png", cv::IMREAD_GRAYSCALE);
EXPECT_TRUE(hidden_mouth_image_filtered.data);
cv::Mat whole_face_image_filtered = cv::imread(output_directory + "/whole_face_filtered.png", cv::IMREAD_GRAYSCALE);
EXPECT_TRUE(whole_face_image_filtered.data);
std::vector<cv::Mat> previous_run_filtered_images;
previous_run_filtered_images.emplace_back(hidden_mouth_image_filtered);
previous_run_filtered_images.emplace_back(whole_face_image_filtered);
cv::Mat hidden_mouth_image = cv::imread("hidden_mouth.png", cv::IMREAD_GRAYSCALE);
EXPECT_TRUE(hidden_mouth_image.data);
cv::Mat whole_face_image = cv::imread("whole_face.png", cv::IMREAD_GRAYSCALE);
EXPECT_TRUE(whole_face_image.data);
std::vector<cv::Mat> test_images;
test_images.emplace_back(hidden_mouth_image);
test_images.emplace_back(whole_face_image);
processImagesForComparison(test_images);
EXPECT_TRUE(areTheSame(test_images, previous_run_filtered_images));
}
std::experimental::filesystem::current_path(original_path);
}
The "areTheSame" will return true. But if I run it in the loop:
TEST(PreprocessingTests, CutAndFilterTest)
{
auto original_path = std::experimental::filesystem::current_path();
std::experimental::filesystem::current_path("../tests/data/");
cv::Mat hidden_mouth_image = cv::imread("hidden_mouth.png", cv::IMREAD_GRAYSCALE);
EXPECT_TRUE(hidden_mouth_image.data);
cv::Mat whole_face_image = cv::imread("whole_face.png", cv::IMREAD_GRAYSCALE);
EXPECT_TRUE(whole_face_image.data);
std::vector<cv::Mat> original_images;
for (int i=0; i < 1; i++)
{
original_images.emplace_back(hidden_mouth_image);
original_images.emplace_back(whole_face_image);
}
auto copied_original_images = cloneMatVector(original_images);
std::vector<cv::Mat> previous_filtered_images;
for (int run = 0; run < 2; run++)
{
std::vector<cv::Mat> run_images = cloneMatVector(original_images);
processImagesForComparison(run_images);
if (!previous_filtered_images.empty())
EXPECT_TRUE(areTheSame(run_images, previous_filtered_images));
previous_filtered_images = cloneMatVector(run_images);
}
EXPECT_TRUE(areTheSame(original_images, copied_original_images));
std::experimental::filesystem::current_path(original_path);
}
then "areTheSame" will fail... In processImagesForComparison only my grabCut implementation will be run on each element:
cv::Mat grabCutSegmentation(const cv::Mat& input)
{
cv::Mat bgModel, fgModel;
cv::Mat mask(input.rows, input.cols, CV_8U);
// let's set all of them to possible background first
mask.setTo(cv::GC_PR_BGD);
// cut out a small area in the middle of the image
int m_rows = 0.75 * input.rows;
int m_cols = 0.6 * input.cols;
// the region of interest
cv::Mat fg_seed = mask(cv::Range(input.rows/2 - m_rows/2, input.rows/2 + m_rows/2),
cv::Range(input.cols/2 - m_cols/2, input.cols/2 + m_cols/2));
// mark it as foreground
fg_seed.setTo(cv::GC_FGD);
// select last 3 rows of the image as background
cv::Mat1b bg_seed = mask(cv::Range(mask.rows-2, mask.rows),cv::Range::all());
bg_seed.setTo(cv::GC_BGD);
cv::Mat colour_input;
cv::cvtColor(input , colour_input , CV_GRAY2RGB);
cv::grabCut(colour_input, mask, cv::Rect(), bgModel, fgModel, 1, cv::GC_INIT_WITH_MASK);
// let's get all foreground and possible foreground pixels
cv::Mat mask_fgpf = ( mask == cv::GC_FGD) | ( mask == cv::GC_PR_FGD);
// and copy all the foreground-pixels to a temporary image
cv::Mat output = cv::Mat::zeros(input.rows, input.cols, CV_8U);
input.copyTo(output, mask_fgpf);
return output;
}
What could be done regarding this? On which level may this problem emerge?