3

I was wondering how it is possible to create effects like a glowing ball or a glowing line in my video frames in OpenCV. Any tips on where I can start or what can I use so I can create simple animations in my output?

Thanks in advance!

Caloyskie
  • 229
  • 5
  • 14

2 Answers2

2

These effects are simple to accomplish with primitive OpenCV pixel operations. Let's say you have your ball identified as a white region in a separate mask image mask. Blur this mask with GaussianBlur and then combine the result with your source image img. For a glow effect, you probably want something like Photoshop's Screen blending mode, which will only brighten the image:

Result Color = 255 - [((255 - Top Color)*(255 - Bottom Color))/255]

The real key to the "glow" effect is using the pixels in the underlying layer as the screen layer. This translates to OpenCV:

cv::Mat mask, img;
...
mask = mask * img; //fill the mask region with pixels from the original image
cv::GaussianBlur(mask, mask, cv::Size(0,0), 4); //blur the mask, 4 pixels radius
mask = mask * 0.50; //a 50% opacity glow
img = 255 - ((255 - mask).mul(255 - img) / 255); //mul for per-element multiply

I did not test this code, so I might have something wrong here. Color Dodge is also a useful blending mode for glows. More here: How does photoshop blend two images together?

Community
  • 1
  • 1
Matt Montag
  • 7,105
  • 8
  • 41
  • 47
0

I wrote a version of the effect that can run both on the CPU and on HW acceleration devices (e.g. GPU). If src is a cv::UMat and you have OpenCL support it will run using OpenCL otherwise if src is a cv::Mat it will run good old CPU code.

template<typename Tmat>
void glow_effect(Tmat& src, int ksize = 100) {
    static Tmat resize;
    static Tmat blur;
    static Tmat src16;

    cv::bitwise_not(src, src);

    //Resize for some extra performance
    cv::resize(src, resize, cv::Size(), 0.5, 0.5);
    //Cheap blur
    cv::boxFilter(resize, resize, -1, cv::Size(ksize, ksize), cv::Point(-1, -1), true, cv::BORDER_REPLICATE);
    //Back to original size
    cv::resize(resize, blur, cv::Size(VIDEO_WIDTH, VIDEO_HEIGHT));

    //Multiply the src image with a blurred version of itself
    cv::multiply(src, blur, src16, 1, CV_16U);
    //Normalize and convert back to CV_8U
    cv::divide(src16, cv::Scalar::all(255.0), src, 1, CV_8U);

    cv::bitwise_not(src, src);
}

kallaballa
  • 337
  • 2
  • 8