Ask Your Question

Revision history [back]

Make the background of the image transparent using a mask

Greetings. How can I make the background of the image transparent using a mask, not a threshold. The essence of the program is as follows: I get the image and try to cut the object from the background. I have already implemented this. Here I found an implementation with threshold: stackoverflow). Here is what I have:

struct comparator{
bool operator() (std::tuple<std::vector<cv::Point>, bool, double> t1,
                 std::tuple<std::vector<cv::Point>, bool, double> t2) {
    return std::get<2>(t1) > std::get<2>(t2);
}

} comparator;

cv::Mat image = cv::imread("C:\\Users\\Sky\\Downloads\\12.png");
cv::Mat grayImg;

// convert to greyscale
cv::cvtColor(image, grayImg, COLOR_BGRA2GRAY);

// finding threshes
cv::Mat thresh;
cv::threshold(grayImg,thresh, 127, 255, THRESH_BINARY_INV | THRESH_OTSU);


// finding contours
std::vector<std::vector<cv::Point>> contours;
std::vector<cv::Vec4i> hierarchy;

findContours( thresh, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0) );


// finding max contour
std::vector<std::tuple<std::vector<cv::Point>, bool, double>> vec;


for(size_t i = 0; i < contours.size(); ++i){

    vec.push_back(std::make_tuple(contours.at(i), cv::isContourConvex(contours.at(i)),cv::contourArea(contours.at(i))));
}

std::sort(vec.begin(), vec.end(), comparator);

std::tuple<std::vector<cv::Point>, bool, double> maxContour;
maxContour = vec.at(0);



// create mask
cv::Mat mask = Mat::zeros(thresh.size(), CV_8S);

for(size_t i = 0; i < contours.size(); ++i){
    cv::fillConvexPoly(mask, std::get<0>(vec.at(i)), Scalar(255,0,0),8,0);
}


// bitwise
cv::Mat res;
cv::bitwise_and(image, image, res, mask);

// show process
imshow("result", res);
imshow("mask", mask);
imshow("canny", thresh);
imshow("source", image);


// create transparent background
Mat dst;

Mat rgb[3];
split(res,rgb);

Mat rgba[4]={rgb[0],rgb[1],rgb[2]};
merge(rgba,4,dst);


// save to file transparent and cropped images
imwrite("C:/Documents/1.png", res);
imwrite("C:/Documents/dst.png",dst);


while (true) {
    if (waitKey() == 27) { //wait for 'esc' key press for 30ms. If 'esc' key is pressed, break loop
        std::cout << "esc key is pressed by user";
        break;
    }
}

return 0;

As we can see, most of the image is lost if threshold is used.

1)Source. 2) Mask. 3) Thresholds. 4) Result without a transparent background. 5) Result with a mask. As you can see, the result with a transparent background has lost color. I would be grateful for any information.

image description

image description

image description

image description

image description