3
votes

I have multiple semi-transparent polygons, each has a RGBA fill color. I want to plot them all on an image by using OpenCV.

The polygons may overlap with each other. And I want to blend the overlapping parts.

I have tried this with System::Drawing::Graphics.FillPolygon in .net and it worked as what I expected. Each polygon added to the canvas only affects the area it is covering and overlapping area is blended between all involved polygons as the image below shows.

enter image description here

However, I cannot get this expected image in OpenCV.

First of all, I cannot simply use cv::fillPoly() or cv::fillConvexPoly because the documentation says:

The functions do not support alpha-transparency when the target image is 4-channel. In this case, the color[3] is simply copied to the repainted pixels. Thus, if you want to paint semi-transparent shapes, you can paint them in a separate buffer and then blend it with the main image.

Neither can I get the desired result by plotting polygons on different cv::Mat and blending them using addWeighted alternatives as suggested here.

The weighted factor I used here is the weighted alpha value for each polygon, i.e.

weight[i] = alpha[i] / sum(alpha[i])
canvas = sum(weight[i] * polygon[i])

The problem with this method is that every polygon will affect all other polygons on the canvas because its alpha value is used in calculating weight for each polygon. When a new polygon is added to the canvas, all pixels on the canvas are changed, not only the area that this polygon covers.

Any ideas on this problem?

1

1 Answers

2
votes

Blending is a more complex topic than it might seem. There are several common blending strategies. A good explanation with pictures can be found in the QML docs (under "mode" parameter): http://doc.qt.io/qt-5/qml-qtgraphicaleffects-blend.html

After you created your matrix that contains the polygon, you have to do the blending yourself, as you already started. In your routine, you are using adaptive normalization of intensity values. This guarantees that there is no over-saturation.

If you want your polygon drawing not affect the overall brightness of the image, you would have to forego the normalization. You just use the blending strategy that fits your application best and only apply a weighting to the polygon, not the source image.

E.g. canvas = canvas + 0.2*polygon[i] (simple addition)

Based on the strategy you want to employ you may need to render the polygon on a black or white backdrop before blending.