本篇介绍一下利用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
#include
#include
#include
#include
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
效果:
以上情况下是图片已经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
#include
#include
#include
#include
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
效果:
图像的区域切割再图像处理和机器视觉当中有着非常重要作用,基于区域图像的目标跟踪算法将定位点和检测区域切割开来,而不是基于整张图像,这样不仅可以降低算法的迭代速度,且能排除图像其他区域噪点的干扰,提高算法整体的鲁棒性。