您当前的位置: 首页 >  opencv

鱼儿-1226

暂无认证

  • 0浏览

    0关注

    1100博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

opencv学习笔记五十九:图像融合之背景替换

鱼儿-1226 发布时间:2020-07-29 10:11:57 ,浏览量:0

以证件照为例,图片中有大部分为背景,先用kmeans对图像进行分割,可以得到背景的标签,然后将图像分为前景和背景两部分,非背景的都当作前景,显示kmeans分割后的图像dst,将原图像前景赋给dst, 背景都设为0,得到kmeans分割后的图像如下,可看到边缘处有一些小蓝边,过渡比较粗超:

 所以设置遮罩层对边缘进行融合,新建掩码mask单通道图像,将前景部分置1,背景部分置0,然后对mask进行腐蚀和高斯模糊,则mask前景部分为1,背景部分为0,边缘部分非0和1。新建结果图像result,对于mask中前景部分,将原图像赋给result,对于mask中背景部分,将随机生成的颜色赋给result,对于边缘部分,对前景和背景进行融合。

可看到边缘融合后的图像看起来就比较和谐了。

 
  1. #include

  2. using namespace cv;

  3.  
  4. int main(int arc, char** argv) {

  5. Mat src = imread("1.jpg");

  6. namedWindow("input", CV_WINDOW_AUTOSIZE);

  7. imshow("input", src);

  8.  
  9. //组装数据并运行KMeans

  10. int width = src.cols;

  11. int height = src.rows;

  12. int dims = src.channels();

  13. int pointsCount = width * height;

  14. Mat points(pointsCount, dims, CV_32F);//kmeans要求的数据为float类型的

  15. int index = 0;

  16. for (int i = 0; i < height; i++) {

  17. for (int j = 0; j < width; j++) {

  18. index = i*width + j;

  19. points.at(index, 0) = src.at(i, j)[0];

  20. points.at(index, 1) = src.at(i, j)[1];

  21. points.at(index, 2) = src.at(i, j)[2];

  22. }

  23. }

  24. Mat bestLabels;

  25. Mat centers;

  26. kmeans(points, 4, bestLabels, TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 10, 0.1),3,2,centers);

  27.  
  28. //去背景+遮罩层

  29. Mat mask(src.size(), CV_8UC1);

  30. index = src.cols * 2 + 2;

  31. int bindex = bestLabels.at(index, 0);//获得kmeans后背景的标签

  32.  
  33. Mat dst;

  34. src.copyTo(dst);

  35. for (int i = 0; i < height; i++) {

  36. for (int j = 0; j < width; j++) {

  37. index = i*width + j;

  38. int label = bestLabels.at(index, 0);

  39. if (label == bindex) {

  40. dst.at(i, j)[0] = 0;

  41. dst.at(i, j)[1] = 0;

  42. dst.at(i, j)[2] = 0;

  43. mask.at(i, j) = 0;

  44. }

  45. else {

  46. mask.at(i, j) = 255;

  47. }

  48. }

  49. }

  50. imshow("mask", mask);

  51. imshow("kmeans", dst);

  52.  
  53. //对掩码进行腐蚀+高斯模糊

  54. Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));

  55. erode(mask, mask, kernel);

  56. imshow("erode mask", mask);

  57. GaussianBlur(mask, mask, Size(3, 3), 0, 0);

  58. imshow("blur mask", mask);

  59.  
  60. //通道混合

  61. Vec3b color;

  62. color[0] = theRNG().uniform(0, 255);

  63. color[1] = theRNG().uniform(0, 255);

  64. color[2] = theRNG().uniform(0, 255);

  65.  
  66. Mat result(src.size(), src.type());

  67. double w = 0.0;

  68. int b = 0, g = 0, r = 0;

  69. int b1 = 0, g1 = 0, r1 = 0;

  70. int b2 = 0, g2 = 0, r2 = 0;

  71.  
  72. for (int i = 0; i < height; i++) {

  73. for (int j = 0; j < width; j++) {

  74. int m = mask.at(i, j);

  75. if (m == 255) {

  76. result.at(i, j) = src.at(i, j);//将原图像中前景赋给结果图像中的前景

  77. }

  78. else if (m == 0) {

  79. result.at(i, j) = color;//将随机生成的颜色赋给结果图像中的背景

  80. }

  81. else {

  82. w = m / 255.0;//权重

  83. //边缘前景

  84. b1 = src.at(i, j)[0];

  85. g1= src.at(i, j)[1];

  86. r1 = src.at(i, j)[2];

  87. //边缘背景

  88. b2 = color[0];

  89. g2 = color[1];

  90. r2 = color[2];

  91. //边缘融合

  92. b = b1*w + b2 *(1.0 - w);

  93. g = g1*w + g2 *(1.0 - w);

  94. r = r1*w + r2 *(1.0 - w);

  95. result.at(i, j)[0] = b;

  96. result.at(i, j)[1] = g;

  97. result.at(i, j)[2] = r;

  98. }

  99. }

  100. }

  101. imshow("result",result);

  102. waitKey(0);

  103. return 0;

  104. }

关注
打赏
1604459285
查看更多评论
立即登录/注册

微信扫码登录

0.0422s