如何在图像上添加徽标作为水印?

时间:2019-09-04 08:53:02

标签: c++ opencv image-processing watermark blending

最近,我对使用OpenCV进行图像处理感兴趣,但是我是新手。

我对很多图像进行了一些简单的图像处理,最后我想为每个图像添加徽标,该徽标是小的png图像。

有很多代码将两个图像融合在一起。这是我用来混合两个图像的示例:

int main( int argc, char** argv )
{
        double alpha = 0.5; double beta; double input;
        Mat src1, src2, dst;

        // main image with real size.(Large)
        src1 = imread("a.jpg");

        // logo which will be used as a watermark.(small size)
        src2 = imread("logo.png");

        namedWindow("Linear Blend", 1);
        beta = ( 1.0 - alpha );

        addWeighted( src1, alpha, src2, beta, 0.0, dst);

        imshow( "Linear Blend", dst );

        waitKey(0);
        return 0;
}

在这里,两个图像应该是相同的类型和相同的尺寸,而我的徽标图像是一个小图像,我想在角落(实际上是在任意点)上融合到主图像中。

有人可以帮助我做到这一点吗? (也许,一种解决方案是从徽标中创建一个与主图像大小相同的矩阵,因此徽标外的每个点都应为零,然后最终将具有相同大小的两个图像融合在一起。)

我的最终代码如下:

int main( int argc, char** argv )
{
        double alpha = 0.5; double beta; double input;
        Mat src1, src2, src2_copy, dst;

        src1 = imread("a.jpg");
        src2 = imread("logo.png");


        resize(src2, src2_copy, src2.size() / 2, 0.5, 0.5);

        int x = 100;
        int y = 100;
        int w = src2_copy.size().width;
        int h = src2_copy.size().height;
        cv::Rect pos = cv::Rect(x, y, w, h);


        dst = src1.clone();

        namedWindow("Linear Blend", 1);
        beta = ( 1.0 - alpha );

        addWeighted(src1(pos), alpha, src2_copy, beta, 0.0, dst);

        imshow("Linear ", dst);


        waitKey(0);
        return 0;
}

1 个答案:

答案 0 :(得分:2)

您可以使用cv::Mat来描述的cv::Rect(见region of interest (ROI))访问x内的{矩形} documentation on the base class,{ {1}},ywidth。这是一种广泛使用的技术,在很多用例中都变得非常方便!

因此,现在您只需要在主图像中设置适当的ROI,然后在其中混合水印即可。让我们看一下以下代码片段:

height

人工主图像如下:

Main image

人造水印图像如下:

Watermark

然后,最终结果如下:

Result

如您所见,

// Artificial main image
cv::Mat img = cv::Mat(300, 300, CV_8UC3, cv::Scalar(128, 128, 128));

// Artificial watermark
cv::Mat wtm = cv::Mat(25, 25, CV_8UC3, cv::Scalar(0, 0, 255));

// Position of watermark in main image
int x = 30;
int y = 35;
int w = wtm.size().width;
int h = wtm.size().height;
cv::Rect pos = cv::Rect(x, y, w, h);

// Blending
double alpha = 0.7;
double beta = (1.0 - alpha);
cv::addWeighted(img(pos), alpha, wtm, beta, 0.0, img(pos));

ROI cv::addWeighted(img(pos), alpha, wtm, beta, 0.0, img(pos)) 用作操作的源和目标,因此可以进行就地混合。如果您想在保留主图像不变的情况下拥有单独的输出图像,则可以在开始时克隆主图像,即

img(pos)

,然后使用cv::Mat dst = img.clone() 而不是dst(pos)进行混合。

希望有帮助!