opencv 实现PNG的透明背景

  1. 转自:http://www.opencv.org.cn/forum.php?mod=viewthread&tid=32871

  2. void overlayImage(const cv::Mat &background, const cv::Mat &foreground,
  3.   cv::Mat &output, cv::Point2i location)
  4. {
  5.   background.copyTo(output);


  6.   // start at the row indicated by location, or at row 0 if location.y is negative.
  7.   for(int y = std::max(location.y , 0); y < background.rows; ++y)
  8.   {
  9.     int fY = y - location.y; // because of the translation

  10.     // we are done of we have processed all rows of the foreground image.
  11.     if(fY >= foreground.rows)
  12.       break;

  13.     // start at the column indicated by location,

  14.     // or at column 0 if location.x is negative.
  15.     for(int x = std::max(location.x, 0); x < background.cols; ++x)
  16.     {
  17.       int fX = x - location.x; // because of the translation.

  18.       // we are done with this row if the column is outside of the foreground image.
  19.       if(fX >= foreground.cols)
  20.         break;

  21.       // determine the opacity of the foregrond pixel, using its fourth (alpha) channel.
  22.       double opacity =
  23.         ((double)foreground.data[fY * foreground.step + fX * foreground.channels() + 3])

  24.         / 255.;


  25.       // and now combine the background and foreground pixel, using the opacity,

  26.       // but only if opacity > 0.
  27.       for(int c = 0; opacity > 0 && c < output.channels(); ++c)
  28.       {
  29.         unsigned char foregroundPx =
  30.           foreground.data[fY * foreground.step + fX * foreground.channels() + c];
  31.         unsigned char backgroundPx =
  32.           background.data[y * background.step + x * background.channels() + c];
  33.         output.data[y*output.step + output.channels()*x + c] =
  34.           backgroundPx * (1.-opacity) + foregroundPx * opacity;
  35.       }
  36.     }
  37.   }
  38. }


  39. This code only works if:

  40.     The background is in BGR colour space.
  41.     The foreground is in BGRA colour space.

  42. The output image will always be of the same size as the background image, in BGR colour space. The position parameter determines how the foreground is placed on top of the background. A position of (100, -50) will move the foreground 100 pixels to the right and 50 pixels up.

  43. It might not be the best solution as it was written in a hurry, so please feel free to improve.

  44. Explanation of the code:
  45. We first copy the background to the output, so we can continue with only the pixels where foreground and background overlap.
  46. We start at the first scanline where they overlap, being either the top row of the background (y=0) or the top row of the foreground (y = position.y), so we take the maximum of these two. We do the same for the column value (x). We use fX and fY (foreground-x and foreground-y) as the current coordinates in the foreground image.
  47. We determine the opacity of the foreground image using its fourth (alpha) channel. If it is > 0, we combine the pixels of the background and foreground for all channels.

  48. We are done if we passed all overlapping pixels and output will now contain an image of the background, overlayed with the transparent foreground image.

  49. Example usage:


  50. int main(int argc, char *argv[])
  51. {
  52.   // add the second parameter "-1" as flag, to make sure the transparancy channel is read!
  53.   cv::Mat foreground = imread("D:/images/foreground.png", -1);
  54.   cv::Mat background = imread("D:/images/background.jpg");
  55.   cv::Mat result;

  56.   overlayImage(background, foreground, result, cv::Point(0,0));
  57.   cv::imshow("result", result);
  58. }
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值