我目前正在使用opencv在白色背景以及X和Y轴上绘制椭圆:
Mat image = Mat::zeros(size,size, CV_8UC3);
image.setTo(Scalar(255,255,255)); /* White background */
/* Draw Axis */
line(image,
Point(originX, 0), /*Point 1*/
Point(originX, size), /*Point 2*/
Scalar(colorAxis.B,colorAxis.G,colorAxis.R), /*Color*/
1, /*Thickness*/
8); /*lineType*/
line(image,
Point(0, originY), /*Point 1*/
Point(size, originY), /*Point 2*/
Scalar(colorAxis.B,colorAxis.G,colorAxis.R), /*Color*/
1, /*Thickness*/
8);
for(i=0; i<numEllipses; i++)
{
ellipse(image,
Point(originX + dataEllipse[k].center[0]*ppu, originY - dataEllipse[k].center[1]*ppu),
Size(dataEllipse[k].axis[0]*ppu, dataEllipse[k].axis[1]*ppu),
-dataEllipse[k].angle,
0,
360,
Scalar(colorEllipse.B, colorEllipse.G, colorEllipse.R),
-1,
CV_FILLED);
}
imshow("Result", image);
waitKey(1);
这是有N个椭圆并且它们重叠。此外,还有一个与颜色相对应的重量值(从蓝色到红色)。我想使用此权重值将其用作alpha参数。
对于我所看到的,可以使用addWeigth函数,但它在两个图像之间,我想用省略号来做。有没有办法做到这一点,或者我必须每个椭圆有一个图像,并使用addWeigth与image0和image1,然后(image0和image1)和image2等等?
感谢您的帮助。
答案 0 :(得分:0)
这是一个简单的示例程序,它使用临时椭圆图像绘制透明椭圆。
请注意,weight = 1表示椭圆不是透明的,而是实心的,因此椭圆的“下方”不再可见。而绘图的顺序确实有所作为!
int main()
{
//cv::Mat input = cv::imread("../inputData/Lenna.png");
cv::Mat background = cv::Mat(512,512, CV_8UC3, cv::Scalar(255,255,255));
std::vector<cv::Point2f> centers;
std::vector<cv::Scalar> colors;
std::vector<cv::Size> axes;
std::vector<float> angles;
std::vector<float> weights;
// make sure that there are same number of entries in each vector.
centers.push_back(cv::Point2f(255, 255));
centers.push_back(cv::Point2f(275, 255));
centers.push_back(cv::Point2f(255, 275));
centers.push_back(cv::Point2f(275, 275));
centers.push_back(cv::Point2f(255, 225));
centers.push_back(cv::Point2f(225, 225));
colors.push_back(cv::Scalar(255,0,0));
colors.push_back(cv::Scalar(0,255,0));
colors.push_back(cv::Scalar(0,0,255));
colors.push_back(cv::Scalar(0,0,0));
colors.push_back(cv::Scalar(0,0,0));
colors.push_back(cv::Scalar(0,255,0));
axes.push_back(cv::Size(128,128));
axes.push_back(cv::Size(128,128));
axes.push_back(cv::Size(128,128));
axes.push_back(cv::Size(128,128));
axes.push_back(cv::Size(128,128));
axes.push_back(cv::Size(128,128));
angles.push_back(0);
angles.push_back(0);
angles.push_back(0);
angles.push_back(0);
angles.push_back(0);
angles.push_back(0);
// weight 0 means completely transparent = invible. weight 1 means completely solid = will overwrite everything else
weights.push_back(0.5f); // half transparent
weights.push_back(0.5f);
weights.push_back(0.5f);
weights.push_back(1.0f); // solid
weights.push_back(0.3f); // quite transparent
weights.push_back(0.3f); // quite transparent
// ORDER DOES MATTER!
// printing a transparent ellipse over a solid ellipse will make the transparent ellipse partly visible, but printing the solid ellipse over anything will make only the solid ellipse visible
// you could however sort ellipses before printing so that more solid ones are more in the background for example
int thickness = 5;
for(unsigned int i=0; i<centers.size(); ++i)
{
cv::Mat temporaryEllipse = cv::Mat::zeros(background.rows, background.cols, background.type()); // same size and type as background;
cv::Mat temporaryMask = cv::Mat::zeros(background.rows, background.cols, CV_8UC1); // empty single channel 8bit mask
// draw ellipse to temporary
cv::ellipse(temporaryEllipse, centers[i], axes[i], angles[i], 0, 360, colors[i], thickness);
// draw same ellipse to mask
cv::ellipse(temporaryMask, centers[i], axes[i], angles[i], 0, 360, 255, thickness);
for(int y=0; y<temporaryEllipse.rows; ++y)
for(int x=0; x<temporaryEllipse.cols; ++x)
{
// only blend pixel that belong to the ellipse!
if(temporaryMask.at<unsigned char>(y,x))
{
cv::Vec3b ellipsePixel = temporaryEllipse.at<cv::Vec3b>(y,x);
cv::Vec3b backgroundPixel = background.at<cv::Vec3b>(y,x);
float weight = weights[i];
cv::Vec3b blendedPixel = weight*ellipsePixel + (1-weight)*backgroundPixel;
// update result
background.at<cv::Vec3b>(y,x) = blendedPixel;
}
}
}
cv::imshow("input", background);
cv::imwrite("../outputData/TransparentEllipses.png", background);
cv::waitKey(0);
return 0;
}
并且这里绘制的厚度为15
答案 1 :(得分:0)
我用两个填充的椭圆测试了你的代码,一个红色和一个蓝色,大小为(1,2)和(2,1),红色为0.8,蓝色为0.2。因此,我应该(或者我想)以红色椭圆@ 0.8和蓝色@0.2结束。它们重叠的地方应该是红色和蓝色的混合,对吧?另外,如果我正确理解了您的代码,第一个椭圆将被完全绘制,但是当绘制第二个椭圆时,将显示仅在它们之间重叠的部分。我对吗? 我得到了你的代码,我最终得到了这个:
cv::Mat background = cv::Mat(size,size, CV_8UC3, cv::Scalar(255,255,255));
int color[nEll][3] = {{255,0,0},{0,0,255}}, y,x, s[nEll][2]={{2,1},{1,2}};
float weights[nEll] = {0.8, 0.2};
for(i=0; i<nEll; i++)
{
Mat temporaryEllipse = Mat::zeros(size,size, CV_8UC3);
Mat temporaryMask = Mat::zeros(size,size,CV_8UC1);
// draw ellipse to temporary
ellipse(temporaryEllipse,
Point(originX + 0.5*ppu, originY - 0.5*ppu),
Size(s[i][0]*ppu, s[i][1]*ppu),
0,//angle
0,
360,
Scalar(color[i][0], color[i][1], color[i][2]),
-1,
CV_FILLED);
// draw same ellipse to mask
ellipse(temporaryMask,
Point(originX + 0.5*ppu, originY - 0.5*ppu),
Size(s[i][0]*ppu, s[i][1]*ppu),
0,//angle
0,
360,
Scalar(color[i][0], color[i][1], color[i][2]),
-1,
CV_FILLED);
for(y=0; y<temporaryEllipse.rows; ++y)
{
for(int x=0; x<temporaryEllipse.cols; ++x)
{
// only blend pixel that belong to the ellipse
if(temporaryMask.at<unsigned char>(y,x))
{
cv::Vec3b ellipsePixel = temporaryEllipse.at<cv::Vec3b>(y,x);
cv::Vec3b backgroundPixel = background.at<cv::Vec3b>(y,x);
cv::Vec3b blendedPixel = weights[i]*ellipsePixel + (1-weights[i])*backgroundPixel;
// update result
background.at<cv::Vec3b>(y,x) = blendedPixel;
}
}
}
}
cv::imshow("input", background);
但是我得到的最后一个椭圆显示为weight = 1。
非常感谢你的帮助。