使用 opencv C++ 将图像连接成单个图像
concatenate the images to single image using opencv C++
我正在根据视频制作单张图片。但是我阅读视频并创建帧,然后旋转帧并裁剪帧,然后保存这些裁剪的帧。
这些裁剪后的帧应该组合起来创建一个图像。
所以我将它们附加到 Mat 的向量中,然后想水平连接它们。
我这样做了,但它没有显示任何图像,也没有保存图像。
我想做类似于python
的事情
list_images = []
for img in glob.glob(crop_dir + "*.jpg"):
n = cv2.imread(img,0)
list_images.append(n)
im_v = np.concatenate(list_images)
cv2.imwrite("finalimg.jpg",im_v)
我的变量imglist
是类型
class std::vector<class cv::Mat,class std::allocator<class cv::Mat> >
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include <filesystem>
using namespace std;
using namespace cv;
namespace fs = std::filesystem;
string crop_dir = "Task2_Resources/CropImages/";
void delete_dir_content(const fs::path& dir_path) {
for (auto& path : fs::directory_iterator(dir_path)) {
fs::remove_all(path);
}
}
int main() {
system("CLS");
if (!fs::is_directory(crop_dir) || !fs::exists(crop_dir)) { // Check if folder exists
fs::create_directory(crop_dir); // create folder
}
delete_dir_content(crop_dir);
VideoCapture vid_capture("Task2_Resources/sample201.avi");
int count = 0;
Mat finalimg,mimg;
vector<cv::Mat> imglist;
Mat image;
int x = 190, y = 59, h = 1, w = 962;
if (!vid_capture.isOpened()){
std::cout << "Cannot open the video file" << endl;
return -1;
}
while (true) {
Mat frame , rimg;
vector<Mat> blocks;
bool isSuccess = vid_capture.read(frame);
if (!isSuccess){
std::cout << "Cannot read the frame from video file" << endl;
break;
}
//imshow("Frames", frame);
count++;
float width = frame.cols;
float height = frame.rows;
Point2f center = Point2f((width / 2), (height / 2));
double degree = -0.2;
double scale = 1.0;
Mat change = getRotationMatrix2D(center, degree, scale); // Rotate & scale
warpAffine(frame, rimg, change, frame.size(), cv::INTER_CUBIC, cv::BORDER_CONSTANT, cv::Scalar(0, 0, 0));
Mat cropped_image = rimg(Range(y,y+h), Range(x, x+w));
string fname = to_string(count) + ".jpg";
cv::imwrite(crop_dir + fname, cropped_image);
imglist.push_back(cropped_image);
}
hconcat(imglist,image);
cout << typeid(imglist).name() << endl;
cv::imwrite("final.jpg", image);
std::cout << "Total frames created " << count << endl;
return 0;
}
Visual Studio 调试控制台
我唯一注意到的问题是 h = 1
- 这使得 cropped_image
的高度只有 1 个像素。
由于您没有报告任何错误消息,我们无法真正说明它为什么不起作用。
我建议您使用调试器,并逐步迭代代码(为此使用 IDE)。
要构建工作示例,您可以按照接下来描述的阶段进行操作。
其中一个问题可能与 sample201.avi
视频文件有关。
为了使答案可重现,我们可以使用 FFmpeg CLI 来创建合成视频文件:
请从控制台执行以下命令(所以我们有相同的输入文件):
ffmpeg -y -f lavfi -i testsrc=size=1280x720:duration=3:rate=1 sample.avi
该命令创建一个具有 3 个视频帧且分辨率为 1280x720 的视频文件。
如果您使用 Windows,您可能需要下载 FFmpeg(在 Linux 中,ffmpeg 通常是“内置的”)。
将 sample.avi
复制到 Task2_Resources
文件夹。
编辑您的 C++ 代码:
将 int x = 190, y = 59, h = 1, w = 962;
替换为:
int x = 190, y = 59, h = 500, w = 962;
(例如使用 500
像素的高度)。
将VideoCapture vid_capture("Task2_Resources/sample201.avi");
替换为VideoCapture vid_capture("Task2_Resources/sample.avi");
执行你的代码。
确保在 CropImages
文件夹中创建了 3 张 JPG 图片。
输出文件 final.jpg
在工作文件夹中创建(确保您具有写入权限)。
示例输出(调整大小):
我正在根据视频制作单张图片。但是我阅读视频并创建帧,然后旋转帧并裁剪帧,然后保存这些裁剪的帧。 这些裁剪后的帧应该组合起来创建一个图像。 所以我将它们附加到 Mat 的向量中,然后想水平连接它们。 我这样做了,但它没有显示任何图像,也没有保存图像。
我想做类似于python
的事情list_images = []
for img in glob.glob(crop_dir + "*.jpg"):
n = cv2.imread(img,0)
list_images.append(n)
im_v = np.concatenate(list_images)
cv2.imwrite("finalimg.jpg",im_v)
我的变量imglist
是类型
class std::vector<class cv::Mat,class std::allocator<class cv::Mat> >
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include <filesystem>
using namespace std;
using namespace cv;
namespace fs = std::filesystem;
string crop_dir = "Task2_Resources/CropImages/";
void delete_dir_content(const fs::path& dir_path) {
for (auto& path : fs::directory_iterator(dir_path)) {
fs::remove_all(path);
}
}
int main() {
system("CLS");
if (!fs::is_directory(crop_dir) || !fs::exists(crop_dir)) { // Check if folder exists
fs::create_directory(crop_dir); // create folder
}
delete_dir_content(crop_dir);
VideoCapture vid_capture("Task2_Resources/sample201.avi");
int count = 0;
Mat finalimg,mimg;
vector<cv::Mat> imglist;
Mat image;
int x = 190, y = 59, h = 1, w = 962;
if (!vid_capture.isOpened()){
std::cout << "Cannot open the video file" << endl;
return -1;
}
while (true) {
Mat frame , rimg;
vector<Mat> blocks;
bool isSuccess = vid_capture.read(frame);
if (!isSuccess){
std::cout << "Cannot read the frame from video file" << endl;
break;
}
//imshow("Frames", frame);
count++;
float width = frame.cols;
float height = frame.rows;
Point2f center = Point2f((width / 2), (height / 2));
double degree = -0.2;
double scale = 1.0;
Mat change = getRotationMatrix2D(center, degree, scale); // Rotate & scale
warpAffine(frame, rimg, change, frame.size(), cv::INTER_CUBIC, cv::BORDER_CONSTANT, cv::Scalar(0, 0, 0));
Mat cropped_image = rimg(Range(y,y+h), Range(x, x+w));
string fname = to_string(count) + ".jpg";
cv::imwrite(crop_dir + fname, cropped_image);
imglist.push_back(cropped_image);
}
hconcat(imglist,image);
cout << typeid(imglist).name() << endl;
cv::imwrite("final.jpg", image);
std::cout << "Total frames created " << count << endl;
return 0;
}
Visual Studio 调试控制台
我唯一注意到的问题是 h = 1
- 这使得 cropped_image
的高度只有 1 个像素。
由于您没有报告任何错误消息,我们无法真正说明它为什么不起作用。
我建议您使用调试器,并逐步迭代代码(为此使用 IDE)。
要构建工作示例,您可以按照接下来描述的阶段进行操作。
其中一个问题可能与 sample201.avi
视频文件有关。
为了使答案可重现,我们可以使用 FFmpeg CLI 来创建合成视频文件:
请从控制台执行以下命令(所以我们有相同的输入文件):
ffmpeg -y -f lavfi -i testsrc=size=1280x720:duration=3:rate=1 sample.avi
该命令创建一个具有 3 个视频帧且分辨率为 1280x720 的视频文件。
如果您使用 Windows,您可能需要下载 FFmpeg(在 Linux 中,ffmpeg 通常是“内置的”)。
将 sample.avi
复制到 Task2_Resources
文件夹。
编辑您的 C++ 代码:
将 int x = 190, y = 59, h = 1, w = 962;
替换为:
int x = 190, y = 59, h = 500, w = 962;
(例如使用 500
像素的高度)。
将VideoCapture vid_capture("Task2_Resources/sample201.avi");
替换为VideoCapture vid_capture("Task2_Resources/sample.avi");
执行你的代码。
确保在 CropImages
文件夹中创建了 3 张 JPG 图片。
输出文件 final.jpg
在工作文件夹中创建(确保您具有写入权限)。
示例输出(调整大小):