解释一下标题:裁块就是将一张图像裁成N*N张子图,除此之外没有别的操作;

拼接就是对这些子图操作完之后,再拼回原来那张图(不是类似于配准那样的拼接);

 一、图像裁成若干子块

引用:C++ opencv 将图片分为任意N等分,并保存所有子图片于本地_opencv图像等分_Wendy_lz的博客-CSDN博客

#include

#include

#include

#include

#include

#include

using namespace cv;

using namespace std;

void cutImage()

{

string s = "D:/AAAA/BBBB/CCCC/" + name + ".png";//图片所在路径

Mat src = imread(s);

vector subImages; //用于存放等分后的各子图

int subImageNum = 10;//子图数量=10*10

int srcHeight, srcWidth, subHeight, subWidth;

srcHeight = src.rows; srcWidth = src.cols;

subHeight = srcHeight / subImageNum;

subWidth = srcWidth / subImageNum;

for (int j = 0; j < subImageNum; j++)

{

for (int i = 0; i < subImageNum; i++)

{

if (j < subImageNum - 1 && i < subImageNum - 1) {

cv::Mat temImage(subHeight, subWidth, CV_8UC3, cv::Scalar(0, 0, 0));

cv::Mat imageROI = src(cv::Rect(i * subWidth, j * subHeight, temImage.cols, temImage.rows));

cv::addWeighted(temImage, 1.0, imageROI, 1.0, 0., temImage);

subImages.push_back(temImage);

}

else {

cv::Mat temImage(srcHeight - (subImageNum - 1) * subHeight, srcWidth - (subImageNum - 1) * subWidth, CV_8UC3, cv::Scalar(0, 0, 0));

cv::Mat imageROI = src(cv::Rect(i * subWidth, j * subHeight, temImage.cols, temImage.rows));

cv::addWeighted(temImage, 1.0, imageROI, 1.0, 0., temImage);

subImages.push_back(temImage);

}

}

}

for (int i = 0; i < subImages.size(); i++)

{

string out = "D:/AAAA/BBBB/EEEE/" + name +"_"+std::to_string(i)+ ".png";//输出保存各子图像

imwrite(out, subImages[i]);

}

}

int main()

{

cutImage();

cv::waitKey(0);

system("pause");

return 0;

}

效果如下,一张单独的图被裁剪成100张子图。

上述裁剪方法,可以知道自己得到几张子图像,但是每张子图像的大小并不完全一致。

自己写了一个简单粗暴的方式,可以固定子图像的行列大小,但是需要扩充原图行列,会产生黑边。

#include

#include

#include

#include

#include

#include

using namespace cv;

using namespace std;

void testsubimg(string name)//将图片分为n*n大小的若干块

{

string s = "D:/AA/BB/CC/" + name + ".png";

Mat src = imread(s);

int n = 128;//子图像大小为n*n格

Mat srcadd;

cv::copyMakeBorder(src, srcadd, 0, (n-(src.rows%n)), 0, (n - (src.cols%n)), CV_8UC1, cv::Scalar::all(0));//向下,向右扩充对应的行列数

vector subbox;

for (int i = 0; i < srcadd.rows; i+=n)

{

for (int j = 0; j < srcadd.cols; j+=n)

{

Mat partImage = srcadd(Rect(j, i, n, n));//切出子图像

subbox.push_back(partImage);

}

}

for (int i = 0; i < subbox.size(); i++)

{

string s1 = "D:/AA/BB/CC/ee/" + name + "_" + std::to_string(i) + ".png";

imwrite(s1, subbox[i]);

}

}

int main()

{

testsubimg("2");

cv::waitKey(0);

system("pause");

return 0;

}

 二、图像横、纵拼接

横向拼接,两张图片的尺寸大小可以不一样。(具体实现使用的下文关键代码)

引用:通过ROI实现图像并排合并_Howardk的博客-CSDN博客

#include

#include

#include

#include

#include

#include

using namespace cv;

using namespace std;

Mat comimage(string name1, string name2) //横向拼接

{

string s1 = "D:/AA/BB/CC/" + name1 + ".png";

Mat img1 = imread(s1);

string s2 = "D:/AA/BB/CC/" + name2 + ".png";

Mat img2 = imread(s2);

int height = img1.rows;

int width1 = img1.cols;

int width2 = img2.cols;

// 将高图像等比缩放与低图像高度一致

if (img1.rows > img2.rows)

{

height = img2.rows;

width1 = img1.cols * ((float)img2.rows / (float)img1.rows);

resize(img1, img1, Size(width1, height));

}

else if (img1.rows < img2.rows)

{

width2 = img2.cols * ((float)img1.rows / (float)img2.rows);

resize(img2, img2, Size(width2, height));

}

//创建目标Mat

Mat des;

des.create(height, width1 + width2, img1.type());

Mat r1 = des(Rect(0, 0, width1, height));

img1.copyTo(r1);

Mat r2 = des(Rect(width1, 0, width2, height));

img2.copyTo(r2);

namedWindow("des");

imshow("des", des);

return des;

}

int main()

{

comimage("1","2");

cv::waitKey(0);

system("pause");

return 0;

}

可以看到用于拼接的两张图尺寸是不一致的,图2会更方。代码是让高度向更小的看齐,并且需要改变的那张图同时还要等比例缩小。

 稍微修改一下,实现纵向拼接。两张拼接的图尺寸可以不一致。

#include

#include

#include

#include

#include

#include

using namespace cv;

using namespace std;

Mat comimage1(string name1, string name2) //纵向拼接

{

string s1 = "D:/00-myfiles/车道线提取/testdata0101/NewPaper/temp/" + name1 + ".png";

Mat img1 = imread(s1);

string s2 = "D:/00-myfiles/车道线提取/testdata0101/NewPaper/temp/" + name2 + ".png";

Mat img2 = imread(s2);

int width = img1.cols;

int height1 = img1.rows;

int height2 = img2.rows;

if (img1.cols > img2.cols)

{

width = img2.cols;

height1 = img1.rows*((float)img2.cols / (float)img1.cols);

resize(img1, img1, Size(width, height1));

}

else if (img1.cols < img2.cols)

{

height2 = img2.rows*((float)img1.cols / (float)img2.cols);

resize(img2, img2, Size(width, height2));

}

Mat des;

des.create(height1 + height2, width, img1.type());

Mat r1 = des(Rect(0, 0, width, height1));

img1.copyTo(r1);

Mat r2 = des(Rect(0, height1, width, height2));

img2.copyTo(r2);

namedWindow("des");

imshow("des", des);

return des;

}

int main()

{

comimage("1","2");

cv::waitKey(0);

system("pause");

return 0;

}

下图是纵向拼接效果,图2不完整是因为屏幕太小了,截图只能截到这么多。

纵向拼接还有一个很简单的实现语句,但是要求图像的尺寸必须是一致的,不然就会报错。

Mat merge;

Mat image;

image.push_back(image);//将image图像加到merge图像的最后一行

三、拼回完整的图像

#include

#include

#include

#include

#include

#include

using namespace cv;

using namespace std;

void com(string name)

{

Mat merge;

for (int k = 0; k < 10; k++)

{

vector box;

for (int i = k * 10; i < (k + 1) * 10; i++)

{

string s = "D:/AA/BB/CC/" + name + "_" + std::to_string(i) + ".png";

Mat src = imread(s);

box.push_back(src);

}

Mat img1 = box[0];

for (int i = 1; i < box.size(); i++)

{

Mat temp = comimage(img1, box[i]);//属于同一行的,横向拼接

img1 = temp;

}

if (k==0)

{

merge= img1;

}

else

{

merge=comimage1(merge, img1);//拼出每行之后,再将中间结果纵向拼接

}

}

namedWindow("img_merge");

imshow("img_merge", merge);

}

int main()

{

com("001");

cv::waitKey(0);

system("pause");

return 0;

}

拼的效果感觉也不是很好,小孩的腿那里明显错位。(个人推测是因为最开始的裁块固定了裁剪数量,每张子图尺寸都不一样,到最后一行的行列数差的最大,经过等比例缩放后就有明显的位移)

相关链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: