如何创建半透明形状?

37

我想知道如何在OpenCV中绘制半透明的形状,类似于下面图片中的形状(来自http://tellthattomycamera.wordpress.com/):

enter image description here

我不需要那些奇特的圆形,但我想要能够在一个三通道彩色图像上绘制一个矩形,并指定矩形的透明度,就像这样:

rectangle (img, Point (100,100), Point (300,300), Scalar (0,125,125,0.4), CV_FILLED);

其中0,125,125是矩形的颜色,0.4指定透明度。 然而,OpenCV的绘图功能中没有这种功能。我该如何在OpenCV中绘制形状,以便可以看到部分原始图像?

4个回答

46

下面的图片使用OpenCV演示了透明度。您需要在图像和矩形之间进行alpha混合。以下是一种实现方法的代码。

enter image description here

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

int main( int argc, char** argv )
{
    cv::Mat image = cv::imread("IMG_2083s.png"); 
    cv::Mat roi = image(cv::Rect(100, 100, 300, 300));
    cv::Mat color(roi.size(), CV_8UC3, cv::Scalar(0, 125, 125)); 
    double alpha = 0.3;
    cv::addWeighted(color, alpha, roi, 1.0 - alpha , 0.0, roi); 

    cv::imshow("image",image);
    cv::waitKey(0);
}

2
感谢您的回复和耐心等待,但我用addWeighted函数以另一种方式解决了它。就像这样: cap >> img; img.copyTo(copy); rectangle(copy, Point(100,100), Point(300.300), Scalar(0,125,125), CV_FILLED, CV_AA, 0); addWeighted(copy, 0.4, 0.1 to 0 .4,0 img, img); imshow("img",img); - Bokonon
2
@Bull,我有一个问题,你在addWeighted函数调用中没有使用image Mat对象,它是如何更新到图像的?谢谢。 - Prakash M
3
@Prakash,“roi”中的数据是“image”数据的矩形切片。也就是说,如果您从“roi”中读取数据,则实际上是从“image”中读取数据,如果您修改“roi”中的数据,则同时也会修改“image”中的数据。 - Bull
1
如何对任意形状或多边形进行操作?我尝试了这个 cv::Mat roi = image(cv::Mat(points));(其中 points 是一个 cv::Point 向量),但它没有起作用。 - Olivia Stork
1
@OliviaStork,简单的方法是使用Alexander Taubenkorb的答案,并将调用cv :: rectangle()的代码替换为在叠加层中绘制任意形状的代码。 - Bull
显示剩余2条评论

20

在OpenCV 3中,这段代码对我起作用:

cv::Mat source = cv::imread("IMG_2083s.png");
cv::Mat overlay;
double alpha = 0.3;

// copy the source image to an overlay
source.copyTo(overlay);

// draw a filled, yellow rectangle on the overlay copy
cv::rectangle(overlay, cv::Rect(100, 100, 300, 300), cv::Scalar(0, 125, 125), -1);

// blend the overlay with the source image
cv::addWeighted(overlay, alpha, source, 1 - alpha, 0, source);

参考/灵感来源:http://bistr-o-mathik.org/2012/06/13/simple-transparency-in-opencv/


3

除了Alexander Taubenkorb的回答之外,您还可以通过替换cv::rectangle行中的形状来绘制随机(半透明)形状。

例如,如果您想要绘制一系列半透明圆形,则可以按照以下方式进行:

cv::Mat source = cv::imread("IMG_2083s.png");  // loading the source image
cv::Mat overlay;  // declaring overlay matrix, we'll copy source image to this matrix
double alpha = 0.3;  // defining opacity value, 0 means fully transparent, 1 means fully opaque

source.copyTo(overlay);  // copying the source image to overlay matrix, we'll be drawing shapes on overlay matrix and we'll blend it with original image

// change this section to draw the shapes you want to draw
vector<Point>::const_iterator points_it;  // declaring points iterator
for( points_it = circles.begin(); points_it != circles.end(); ++points_it )  // circles is a vector of points, containing center of each circle
    circle(overlay, *points_it, 1, (0, 255, 255), -1);  // drawing circles on overlay image


cv::addWeighted(overlay, alpha, source, 1 - alpha, 0, source);  // blending the overlay (with alpha opacity) with the source image (with 1-alpha opacity)

1

对于C ++,我个人喜欢使用重载运算符来进行标量乘法和矩阵加法的可读性:

... same initial lines as other answers above ...

// blend the overlay with the source image
source = source * (1.0 - alpha) + overlay * alpha;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接