OpenCV for Faster Background Recovery in Watermark Removal

60 Views Asked by At

I am working on a watermark removal project using OpenCV in C++. The goal is to recover the background from a composite image by separating it from the foreground (watermark). The code processes the image in blocks and applies some matrix operations to each block. While functional, the code's performance is slower than desired. I'm seeking advice on how to optimize it for speed.

I am working with an image, referred to as composite, which consists of a background overlaid with a watermark (foreground). My objective is to use this composite image, along with a known foreground (watermark), to accurately compute and extract the background image, free of any watermark.

Here's the main part of my code:

void processBlock(const cv::Mat& compositeBlock, const cv::Mat& foregroundBlock, cv::Mat& backgroundBlock, const cv::Mat& alpha, const cv::Mat& denom) {
    // The difference is significant, proceed with background recovery
    std::vector<cv::Mat> compositeChannels(3), foregroundChannels(3);
    cv::split(compositeBlock, compositeChannels);
    cv::split(foregroundBlock, foregroundChannels);
    std::vector<cv::Mat> backChannels(3);

    for (int i = 0; i < 3; ++i) {
        compositeChannels[i].convertTo(compositeChannels[i], CV_32F);
        foregroundChannels[i].convertTo(foregroundChannels[i], CV_32F);
        cv::Mat temp = compositeChannels[i] - foregroundChannels[i].mul(alpha);
        cv::Mat bgCalc;
        cv::divide(temp, denom, bgCalc);
        cv::threshold(bgCalc, bgCalc, 255, 255, cv::THRESH_TRUNC);
        cv::threshold(bgCalc, bgCalc, 0, 0, cv::THRESH_TOZERO);
        bgCalc.convertTo(backChannels[i], CV_8U);
    }
    backChannels.push_back(cv::Mat(compositeBlock.size(), CV_8U, cv::Scalar(255)));
    cv::merge(backChannels, backgroundBlock);}

cv::Mat Watermark::recoverBackground(const cv::Mat& composite, const cv::Mat& foreground) {
auto start = std::chrono::high_resolution_clock::now();

// Alpha channel preparation
std::vector<cv::Mat> foregroundChannels(4);
cv::split(foreground, foregroundChannels);
cv::Mat alpha;
foregroundChannels[3].convertTo(alpha, CV_32F, 1.0 / 255.0);
const float epsilon = 1e-4;
cv::Mat denom = 1.0f - alpha + epsilon;

cv::Mat background(composite.size(), composite.type());
processBlock(composite, foreground, background, alpha, denom);
background.copyTo(background);


auto finish = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> elapsed = finish - start;
std::cout << "Function `recoverBackground` took " << elapsed.count() << " seconds." << std::endl;

return background;}

Are there any inefficiencies in the way I'm handling the matrix operations that could be streamlined? Is the parallel processing with OpenMP being utilized effectively, or are there better ways to parallelize this workload? Any suggestions for alternative approaches or techniques in OpenCV that could speed up this process?

0

There are 0 best solutions below