OpenCV关于图像的区域切割与补全(附Python和C++版本)

本篇介绍一下利用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);
}

效果:

 总结:

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

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>