如何绘制透明多边形?

时间:2015-11-18 22:51:18

标签: c++ opencv

我想画一个透明的多边形(在这种情况下为三角形)。但我无法通过搜索网络找到任何示例。

// Create image
Mat image = Mat::zeros( 400, 400, CV_8UC3 );

// Draw a circle 
/** Create some points */
Point Treangle_points[1][20];
Treangle_points[0][0] = Point( 150, 100 );
Treangle_points[0][1] = Point( 275, 350 );
Treangle_points[0][2] = Point( 50, 20 );

const Point* ppt[1] = { Treangle_points[0] };
int npt[] = { 3 };

fillPoly( image, ppt, npt, 1, Scalar( 255, 255, 255 ), 8 );
imshow("Image",image);

3 个答案:

答案 0 :(得分:3)

要使用透明度,您需要在BGRA色彩空间中使用alpha频道。 alpha = 0表示完全透明,而alpha = 255表示不透明的颜色。

你需要创建一个CV_8UC4图像(又名Mat4b),或者将一个3通道图像转换为带有cvtColor(src, dst, COLOR_BGR2BGRA)的4通道,并绘制一个透明的填充形状,alpha通道等于到0。

如果您加载4频道图片,请记得使用imread("path_to_image", IMREAD_UNCHANGED);

透明三角形(透明度在这里呈现为白色,您可以看到图像实际上是透明的,用您首选的图像查看器打开它):

enter image description here

代码:

#include <opencv2/opencv.hpp>
#include <vector>
using namespace std;
using namespace cv;

int main()
{
    // Create a BGRA green image 
    Mat4b image(300, 300, Vec4b(0,255,0,255));

    vector<Point> vertices{Point(100, 100), Point(200, 200), Point(200, 100)};

    vector<vector<Point>> pts{vertices};
    fillPoly(image, pts, Scalar(0,0,0,0));
    //                                ^ this is the alpha channel                              

    imwrite("alpha.png", image);
    return 0;
}

注意

imshow无法正确显示透明度,因为它只会忽略alpha频道。

C ++ 98版

#include <opencv2/opencv.hpp>
using namespace cv;

int main()
{
    // Create a BGRA green image 
    Mat4b image(300, 300, Vec4b(0, 255, 0, 255));

    Point vertices[3];
    vertices[0] = Point(100, 100);
    vertices[1] = Point(200, 200);
    vertices[2] = Point(200, 100);

    const Point* ppt[1] = { &vertices[0] };
    int npt[] = { 3 };

    fillPoly(image, ppt, npt, 1, Scalar(0, 0, 0, 0), 8);

    imwrite("alpha.png", image);

    imshow("a", image);
    waitKey();

    return 0;
}

答案 1 :(得分:1)

这个问题确实是一个古老的问题。我找到了一些答案,但这不是我想要的。我想设置一个多边形roi透明,在没有alpha通道帮助的情况下将其重叠。我们仍然可以在没有4通道图像的情况下通过透明区域观察背景: a quadrangle transparent area

代码如下:

// img: input 3 channels image
// roi : polygon represents by points
// color: transparent base color
// alpha: transparent ratio
// out:   out image with transparent area
void SetTransparentColor(cv::Mat &img, vector<vector<cv::Point> > &roi, cv::Scalar color, double alpha, cv::Mat &out)
{
  cv::Mat layer = cv::Mat::zeros(img.size(), CV_8UC3);

  cv::fillPoly(layer, roi, color);

  cv::addWeighted(img, alpha, layer, 1-alpha, 0, out);
}

我还尝试了其他方法,并且核心思想是相同的,即通过合并两个具有alpha值的区域像素(代表透明比率)。但是它们很耗时。所以我不会在这里放这些代码。

答案 2 :(得分:0)

作为Miki答案的补充,下面的示例代码可能很有用。

有关详细信息,请参阅http://answers.opencv.org/question/73114

另见sample code of OpenCV documentation

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"

using namespace cv;

int main( int, char** argv )
{
    Mat image(400, 400, CV_8UC4, Scalar(0, 0, 200,0));
    Mat bgra[4];
    split(image,bgra);

    rectangle(bgra[3],Rect(100,100,200,200),Scalar(255),-1);

    merge(bgra,4,image);
    imwrite("transparent1.png",image);

    rectangle(bgra[3],Rect(150,150,100,100),Scalar(127),-1);
    merge(bgra,4,image);
    imwrite("transparent2.png",image);

    bgra[3] = bgra[3] * 0.5; // here you can change transparency %50
    // bgra[3] = bgra[3] + 50 // you can add some value
    // bgra[3] = bgra[3] - 50 // you can subtract some value

    merge(bgra,4,image);
    imwrite("transparent3.png",image);

    waitKey(0);
    return(0);
}