赞
踩
本篇介绍一下利用OpenCV对一整张图像进行分块切割的方案,首先介绍按照等比切割,即将图像的大小按照长宽的比例切割成多少分,俗称“切豆腐块”,如我需要将一块图像切割成m×n块子区域,但是图像的宽和高必须是m和n的整倍数。
话不多说,直接上代码。
Python版本:
- import cv2
-
- x_size = 640
- y_size = 640
-
- img = cv2.imread("touxiang.jpg")
- img = cv2.resize(img,(x_size,y_size))
- cv2.imshow("frame",img)
-
- x_num = 5
- y_num = 5
- w = int(x_size/x_num)
- h = int(y_size/y_num)
-
-
- for m in range(x_num):
- for n in range(y_num):
- imgmn = img[m*w:m*w+w, n*h:n*h+h].copy()
- cv2.imshow("frame"+str(m)+str(n), imgmn)
- cv2.imwrite("touxiang"+str(m)+str(n)+".jpg",imgmn)
- cv2.waitKey(1)
-
- cv2.waitKey(0)
C++版本:
- #include <iostream>
- #include <opencv2/highgui/highgui_c.h>
- #include <opencv2/opencv.hpp>
- #include <opencv2/highgui.hpp>
- #include <opencv2/objdetect.hpp>
- using namespace std;
-
- cv::Mat img;
- cv::Rect inital_Area;
-
- int x_size = 640;
- int y_size = 640;
-
- int x_num = 5;
- int y_num = 5;
- int w = x_size / x_num;
- int h = y_size / y_num;
-
- void main()
- {
- img = cv::imread("touxiang.jpg");
- cv::resize(img, img, cv::Size(x_size, y_size));
- cv::imshow("frame", img);
- for (size_t m = 0; m < x_num; m++)
- {
- for (size_t n = 0; n <y_num; n++)
- {
- inital_Area = cv::Rect(m * w, n * h, w, h);
- cv::Mat imgmn = img(inital_Area);
- cv::imshow("frame"+to_string(m)+to_string(n), imgmn);
- cv::waitKey(1);
- }
- }
- cv::waitKey(0);
- }
效果:
以上情况下是图片已经resize成了640×640的大小,而上种的“切豆腐块”的方法是指定的m×n块的大小,代码里面指定的m和n都为5,640÷5正好能够整除,所以每小块“豆腐”的大小就是128×128,整张图片被切割成25块。
那么接下来的问题是,如果指定每块“小豆腐”的大小,一整张图片万一到边界的地方,图片不够切一整块怎么办呢?扔掉不要?那必然不行,做视觉任务一定要保证图像信息的完整性,因此,最佳的办法就是进行图像补全,简而言之就是把最后的“边角料”,用一些颜色背景来填充成一块完整大小的“豆腐块”。
同样,我们原始完整图片的大小依旧resize成640×640,但是我们在这里指定的子图片的大小为150×150,那么我们简单计算一下,图片长宽各分成4等分,并且会余下40的边角料,因此需要写一个简单的算法来进行判断并补全。
话不多说直接上代码。
Python版本:
- import cv2
-
- x_size = 640
- y_size = 640
-
- img = cv2.imread("touxiang.jpg")
- img = cv2.resize(img,(x_size,y_size))
- cv2.imshow("frame",img)
-
- w = 150
- h = 150
- x_num = int(x_size/w) + 1
- y_num = int(y_size/h) + 1
-
- print(x_num,y_num)
-
- for m in range(x_num):
- for n in range(y_num):
- if n*h+h < y_size and m*w+w < x_size:
- imgmn = img[m * w:m * w + w, n * h:n * h + h].copy()
- elif n*h+h < y_size and m*w+w > x_size:
- imgmn = img[m * w:x_size, n * h:n * h + h].copy()
- imgmn = cv2.copyMakeBorder(imgmn, 0 ,w-(x_size-m * w), 0, 0, cv2.BORDER_CONSTANT, value=[0, 0, 0])
- elif n*h+h > y_size and m*w+w < x_size:
- imgmn = img[m * w:m * w + w, n * h:y_size].copy()
- imgmn = cv2.copyMakeBorder(imgmn, 0 ,0, 0, h-(y_size-h * n), cv2.BORDER_CONSTANT, value=[0, 0, 0])
- else:
- imgmn = img[m * w:x_size, n * h:y_size].copy()
- imgmn = cv2.copyMakeBorder(imgmn, 0, w-(x_size-m * w), 0, h-(y_size-h * n), cv2.BORDER_CONSTANT, value=[0, 0, 0])
-
- cv2.imshow("frame"+str(m)+str(n), imgmn)
- cv2.imwrite("touxiang"+str(m)+str(n)+".jpg",imgmn)
- cv2.waitKey(1)
-
- cv2.waitKey(0)
C++版本:
- #include <iostream>
- #include <opencv2/highgui/highgui_c.h>
- #include <opencv2/opencv.hpp>
- #include <opencv2/highgui.hpp>
- #include <opencv2/objdetect.hpp>
- using namespace std;
-
- cv::Mat img, img_c;
- cv::Rect inital_Area;
-
- int x_size = 640;
- int y_size = 640;
-
- int w = 150;
- int h = 150;
-
- int x_num = x_size / w + 1;
- int y_num = y_size / h + 1;
-
- cv::Mat Cutting_and_completion(int m, int n)
- {
- if (m * w + w <= x_size && n * h + h <= y_size)
- {
- inital_Area = cv::Rect(m * w, n * h, w, h);
- return img(inital_Area);
- }
- else if (m * w + w > x_size && n * h + h <= y_size)
- {
- inital_Area = cv::Rect(m * w, n * h, x_size - m * w, h);
- cv::copyMakeBorder(img(inital_Area), img_c, 0, 0, 0, w - (x_size - m * w), cv::BORDER_CONSTANT, cv::Scalar{ 0, 0,0 });
- return img_c;
- }
- else if (m * w + w <= x_size && n * h + h > y_size)
- {
- inital_Area = cv::Rect(m * w, n * h, w, y_size - n * h);
- cv::copyMakeBorder(img(inital_Area), img_c, 0, h - (y_size - n * h), 0, 0, cv::BORDER_CONSTANT, cv::Scalar{ 0, 0,0 });
- return img_c;
- }
- else
- {
- inital_Area = cv::Rect(m * w, n * h, x_size - m * w, y_size - n * h);
- 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 });
- return img_c;
- }
- }
-
- void main()
- {
- img = cv::imread("touxiang.jpg");
- cv::resize(img, img, cv::Size(x_size, y_size));
- cv::imshow("frame", img);
- for (size_t m = 0; m < x_num; m++)
- {
- for (size_t n = 0; n <y_num; n++)
- {
- cv::Mat imgmn = Cutting_and_completion(m, n);
- cv::imshow("frame"+to_string(m)+to_string(n), imgmn);
- cv::waitKey(1);
- }
- }
- cv::waitKey(0);
- }
效果:
图像的区域切割再图像处理和机器视觉当中有着非常重要作用,基于区域图像的目标跟踪算法将定位点和检测区域切割开来,而不是基于整张图像,这样不仅可以降低算法的迭代速度,且能排除图像其他区域噪点的干扰,提高算法整体的鲁棒性。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。