当前位置:   article > 正文

OpenCV关于图像的区域切割与补全(附Python和C++版本)_opencv 填充非封闭区域

opencv 填充非封闭区域

本篇介绍一下利用OpenCV对一整张图像进行分块切割的方案,首先介绍按照等比切割,即将图像的大小按照长宽的比例切割成多少分,俗称“切豆腐块”,如我需要将一块图像切割成m×n块子区域,但是图像的宽和高必须是m和n的整倍数。

话不多说,直接上代码。

Python版本:

  1. import cv2
  2. x_size = 640
  3. y_size = 640
  4. img = cv2.imread("touxiang.jpg")
  5. img = cv2.resize(img,(x_size,y_size))
  6. cv2.imshow("frame",img)
  7. x_num = 5
  8. y_num = 5
  9. w = int(x_size/x_num)
  10. h = int(y_size/y_num)
  11. for m in range(x_num):
  12. for n in range(y_num):
  13. imgmn = img[m*w:m*w+w, n*h:n*h+h].copy()
  14. cv2.imshow("frame"+str(m)+str(n), imgmn)
  15. cv2.imwrite("touxiang"+str(m)+str(n)+".jpg",imgmn)
  16. cv2.waitKey(1)
  17. cv2.waitKey(0)

C++版本:

  1. #include <iostream>
  2. #include <opencv2/highgui/highgui_c.h>
  3. #include <opencv2/opencv.hpp>
  4. #include <opencv2/highgui.hpp>
  5. #include <opencv2/objdetect.hpp>
  6. using namespace std;
  7. cv::Mat img;
  8. cv::Rect inital_Area;
  9. int x_size = 640;
  10. int y_size = 640;
  11. int x_num = 5;
  12. int y_num = 5;
  13. int w = x_size / x_num;
  14. int h = y_size / y_num;
  15. void main()
  16. {
  17. img = cv::imread("touxiang.jpg");
  18. cv::resize(img, img, cv::Size(x_size, y_size));
  19. cv::imshow("frame", img);
  20. for (size_t m = 0; m < x_num; m++)
  21. {
  22. for (size_t n = 0; n <y_num; n++)
  23. {
  24. inital_Area = cv::Rect(m * w, n * h, w, h);
  25. cv::Mat imgmn = img(inital_Area);
  26. cv::imshow("frame"+to_string(m)+to_string(n), imgmn);
  27. cv::waitKey(1);
  28. }
  29. }
  30. cv::waitKey(0);
  31. }

效果:

以上情况下是图片已经resize成了640×640的大小,而上种的“切豆腐块”的方法是指定的m×n块的大小,代码里面指定的m和n都为5,640÷5正好能够整除,所以每小块“豆腐”的大小就是128×128,整张图片被切割成25块。

那么接下来的问题是,如果指定每块“小豆腐”的大小,一整张图片万一到边界的地方,图片不够切一整块怎么办呢?扔掉不要?那必然不行,做视觉任务一定要保证图像信息的完整性,因此,最佳的办法就是进行图像补全,简而言之就是把最后的“边角料”,用一些颜色背景来填充成一块完整大小的“豆腐块”。

同样,我们原始完整图片的大小依旧resize成640×640,但是我们在这里指定的子图片的大小为150×150,那么我们简单计算一下,图片长宽各分成4等分,并且会余下40的边角料,因此需要写一个简单的算法来进行判断并补全。

话不多说直接上代码。

Python版本:

  1. import cv2
  2. x_size = 640
  3. y_size = 640
  4. img = cv2.imread("touxiang.jpg")
  5. img = cv2.resize(img,(x_size,y_size))
  6. cv2.imshow("frame",img)
  7. w = 150
  8. h = 150
  9. x_num = int(x_size/w) + 1
  10. y_num = int(y_size/h) + 1
  11. print(x_num,y_num)
  12. for m in range(x_num):
  13. for n in range(y_num):
  14. if n*h+h < y_size and m*w+w < x_size:
  15. imgmn = img[m * w:m * w + w, n * h:n * h + h].copy()
  16. elif n*h+h < y_size and m*w+w > x_size:
  17. imgmn = img[m * w:x_size, n * h:n * h + h].copy()
  18. imgmn = cv2.copyMakeBorder(imgmn, 0 ,w-(x_size-m * w), 0, 0, cv2.BORDER_CONSTANT, value=[0, 0, 0])
  19. elif n*h+h > y_size and m*w+w < x_size:
  20. imgmn = img[m * w:m * w + w, n * h:y_size].copy()
  21. imgmn = cv2.copyMakeBorder(imgmn, 0 ,0, 0, h-(y_size-h * n), cv2.BORDER_CONSTANT, value=[0, 0, 0])
  22. else:
  23. imgmn = img[m * w:x_size, n * h:y_size].copy()
  24. imgmn = cv2.copyMakeBorder(imgmn, 0, w-(x_size-m * w), 0, h-(y_size-h * n), cv2.BORDER_CONSTANT, value=[0, 0, 0])
  25. cv2.imshow("frame"+str(m)+str(n), imgmn)
  26. cv2.imwrite("touxiang"+str(m)+str(n)+".jpg",imgmn)
  27. cv2.waitKey(1)
  28. cv2.waitKey(0)

C++版本:

  1. #include <iostream>
  2. #include <opencv2/highgui/highgui_c.h>
  3. #include <opencv2/opencv.hpp>
  4. #include <opencv2/highgui.hpp>
  5. #include <opencv2/objdetect.hpp>
  6. using namespace std;
  7. cv::Mat img, img_c;
  8. cv::Rect inital_Area;
  9. int x_size = 640;
  10. int y_size = 640;
  11. int w = 150;
  12. int h = 150;
  13. int x_num = x_size / w + 1;
  14. int y_num = y_size / h + 1;
  15. cv::Mat Cutting_and_completion(int m, int n)
  16. {
  17. if (m * w + w <= x_size && n * h + h <= y_size)
  18. {
  19. inital_Area = cv::Rect(m * w, n * h, w, h);
  20. return img(inital_Area);
  21. }
  22. else if (m * w + w > x_size && n * h + h <= y_size)
  23. {
  24. inital_Area = cv::Rect(m * w, n * h, x_size - m * w, h);
  25. cv::copyMakeBorder(img(inital_Area), img_c, 0, 0, 0, w - (x_size - m * w), cv::BORDER_CONSTANT, cv::Scalar{ 0, 0,0 });
  26. return img_c;
  27. }
  28. else if (m * w + w <= x_size && n * h + h > y_size)
  29. {
  30. inital_Area = cv::Rect(m * w, n * h, w, y_size - n * h);
  31. cv::copyMakeBorder(img(inital_Area), img_c, 0, h - (y_size - n * h), 0, 0, cv::BORDER_CONSTANT, cv::Scalar{ 0, 0,0 });
  32. return img_c;
  33. }
  34. else
  35. {
  36. inital_Area = cv::Rect(m * w, n * h, x_size - m * w, y_size - n * h);
  37. cv::copyMakeBorder(img(inital_Area), img_c, 0, h - (y_size - n * h), 0, w - (x_size - m * w), cv::BORDER_CONSTANT, cv::Scalar{ 0, 0,0 });
  38. return img_c;
  39. }
  40. }
  41. void main()
  42. {
  43. img = cv::imread("touxiang.jpg");
  44. cv::resize(img, img, cv::Size(x_size, y_size));
  45. cv::imshow("frame", img);
  46. for (size_t m = 0; m < x_num; m++)
  47. {
  48. for (size_t n = 0; n <y_num; n++)
  49. {
  50. cv::Mat imgmn = Cutting_and_completion(m, n);
  51. cv::imshow("frame"+to_string(m)+to_string(n), imgmn);
  52. cv::waitKey(1);
  53. }
  54. }
  55. cv::waitKey(0);
  56. }

效果:

 总结:

        图像的区域切割再图像处理和机器视觉当中有着非常重要作用,基于区域图像的目标跟踪算法将定位点和检测区域切割开来,而不是基于整张图像,这样不仅可以降低算法的迭代速度,且能排除图像其他区域噪点的干扰,提高算法整体的鲁棒性。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/678652
推荐阅读
相关标签
  

闽ICP备14008679号