Watermarking Images: preserve quality, control opacity

asked 2018-07-25 02:24:11 -0600

sazr gravatar image

I set myself a task to create a simple OpenCV program to watermark image. The program will overlay a logo on the bottom right of an image. It will place the logo there with full opacity or slightly transparent. I have some questions whether I have done things correctly and what I can improve.

  • Q1: How can I control the opacity of the logo when I call cv::addWeighted()? I have tried different beta values but they always turn out the same more or less
  • Q2: Does my code preserve the image quality? I don't think it does, for example; the image I load in is 2mb and when I watermark then save it as a JPEG it is 100kb so I've lost quality. How can I preserve quality?
  • Q3: The logo image will always be a PNG with transparent (black?) background. When I threshold to create a mask of the logo I get artifacts or an unclean extraction of the logo. How could I accurately extract the logo without artifacts or losing detail?

    Mat src = imread("./images/pan1.jpg");  
    Mat logo = imread("./images/logo.png"); 
    
    // Watermark image: overlay logo slightly faded/transparent
    Mat watermarked;
    Mat logoResized = Mat(src.rows, src.cols, CV_8UC3);
    // Make the logo image same size as the src image
    copyMakeBorder(logo, logoResized, src.rows - logo.rows, 0, src.cols - logo.cols, 0, BORDER_CONSTANT, { 0,0,0 });
    addWeighted(src, 1.0, logoResized, 1.0, 0, watermarked); // Q1
    imshow("Watermarked Opacity", watermarked);
    imwrite("./images/pan-watermarked1.jpg", watermarked);
    
    
    // Overlay logo
    Mat logoGray, thresh;
    cvtColor(logo, logoGray, CV_BGR2GRAY);
    threshold(logoGray, thresh, 1, 255, CV_THRESH_BINARY);
    Rect r(res.cols-logo.cols, res.rows-logo.rows, logo.cols, logo.rows);
    logo.copyTo(src(r), thresh);
    imshow("Watermarked", src);
    imwrite("./images/pan-watermarked2.jpg", src);
    
edit retag flag offensive close merge delete

Comments

1

you CAN'T achieve transparency with 3 channels only

berak gravatar imageberak ( 2018-07-25 02:37:04 -0600 )edit

@berak my understanding is that the png is loaded/read in as a 4 channel Mat where the 4th channel is the alpha. So I am considering the transparency.

sazr gravatar imagesazr ( 2018-07-25 02:39:01 -0600 )edit
1

well, IF your alpha channel is binary, you can use copyTo() and use that alpha as a mask.

if it's NOT binary, but continuous -- you'll have to write your own, low-level alpha blending code. (please look it up). addWeighted does linear blending, and can't help you here.

and again, opencv is a computer-vision library. it's not meant to be photoshop.

berak gravatar imageberak ( 2018-07-25 02:44:02 -0600 )edit