赞
踩
解释一下标题:裁块就是将一张图像裁成N*N张子图,除此之外没有别的操作;
拼接就是对这些子图操作完之后,再拼回原来那张图(不是类似于配准那样的拼接);
引用:C++ opencv 将图片分为任意N等分,并保存所有子图片于本地_opencv图像等分_Wendy_lz的博客-CSDN博客
- #include<iostream>
- #include<fstream>
- #include<opencv2/imgproc/imgproc.hpp>
- #include<opencv2/core/core.hpp>
- #include<opencv2/highgui/highgui.hpp>
- #include<vector>
-
- using namespace cv;
- using namespace std;
-
- void cutImage()
- {
- string s = "D:/AAAA/BBBB/CCCC/" + name + ".png";//图片所在路径
- Mat src = imread(s);
-
- vector<Mat> 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<iostream>
- #include<fstream>
- #include<opencv2/imgproc/imgproc.hpp>
- #include<opencv2/core/core.hpp>
- #include<opencv2/highgui/highgui.hpp>
- #include<vector>
-
- 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<Mat> 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;
- }
横向拼接,两张图片的尺寸大小可以不一样。(具体实现使用的下文关键代码)
- #include<iostream>
- #include<fstream>
- #include<opencv2/imgproc/imgproc.hpp>
- #include<opencv2/core/core.hpp>
- #include<opencv2/highgui/highgui.hpp>
- #include<vector>
-
- 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<iostream>
- #include<fstream>
- #include<opencv2/imgproc/imgproc.hpp>
- #include<opencv2/core/core.hpp>
- #include<opencv2/highgui/highgui.hpp>
- #include<vector>
-
- 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<iostream>
- #include<fstream>
- #include<opencv2/imgproc/imgproc.hpp>
- #include<opencv2/core/core.hpp>
- #include<opencv2/highgui/highgui.hpp>
- #include<vector>
-
- using namespace cv;
- using namespace std;
-
- void com(string name)
- {
- Mat merge;
- for (int k = 0; k < 10; k++)
- {
- vector<Mat> 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;
- }
拼的效果感觉也不是很好,小孩的腿那里明显错位。(个人推测是因为最开始的裁块固定了裁剪数量,每张子图尺寸都不一样,到最后一行的行列数差的最大,经过等比例缩放后就有明显的位移)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。