OpenCV Mat操作
使用 reshape 方法改变 4D Mat 形状
#include <opencv2/opencv.hpp>
int main()
{
// Create a 4D Mat with dimensions (3, 3, 3, 3)
cv::Mat mat(3, 3, CV_32F, cv::Scalar(0));
// Reshape the Mat to (3, 3, 9)
mat = mat.reshape(3, cv::Size(3, 3, 9));
// Check the new shape of the Mat
std::cout << "mat.dims: " << mat.dims << std::endl;
std::cout << "mat.size: " << mat.size << std::endl;
return 0;
}
在此示例中,创建了一个尺寸为 (3, 3, 3, 3) 的 4D Mat,然后使用重塑方法将其重塑为 (3, 3, 9)。reshape 方法的第一个参数是重塑 Mat 中的通道数,在此示例中设置为 3。第二个参数是重塑后的 Mat 的大小,在本例中设置为 (3, 3, 9)。然后将 Mat 的新形状打印到控制台。
重要的是要注意,重塑 Mat 会改变内存中的底层数据布局,因此它可能会对性能产生影响,并且了解重塑的作用很重要。
更改 4D Mat 尺寸顺序
#include <opencv2/opencv.hpp>
int main()
{
// Create a 4D Mat with dimensions (3, 3, 3, 3)
cv::Mat mat(3, 3, 3, 3, CV_32F, cv::Scalar(0));
// Permute the dimensions of the Mat to (3, 3, 9, 3)
cv::Mat permuted_mat;
cv::transpose(mat, permuted_mat, cv::Vec4i(0, 2, 3, 1));
// Check the new shape of the Mat
std::cout << "permuted_mat.dims: " << permuted_mat.dims << std::endl;
std::cout << "permuted_mat.size: " << permuted_mat.size << std::endl;
return 0;
}
在此示例中,创建了一个尺寸为 (3, 3, 3, 3) 的 4D Mat,然后使用该方法将 Mat 的尺寸排列为 (3, 3, 9, 3) permute。该permute方法接受一个cv::Vec4i包含维度新顺序的对象。在此示例中,维度从 (0, 1, 2, 3) 置换为 (0, 2, 3, 1)。 重要的是要注意,排列 Mat 的维度不会改变内存中的底层数据布局,它只会改变数据的索引方式。当您想要更改数据的表示方式以用于特定操作或可视化目的时,这会很有用。
连接第二个维度 4D Mat
#include <opencv2/opencv.hpp>
int main()
{
// Create two 4D Mats with dimensions (3, 3, 3, 3)
cv::Mat mat1(3, 3, 3, 3, CV_32F, cv::Scalar(0));
cv::Mat mat2(3, 3, 3, 3, CV_32F, cv::Scalar(1));
// Concatenate the Mats along the second dimension
cv::Mat concatenated_mat;
cv::hconcat(mat1, mat2, concatenated_mat);
// Check the new shape of the concatenated Mat
std::cout << "concatenated_mat.dims: " << concatenated_mat.dims << std::endl;
std::cout << "concatenated_mat.size: " << concatenated_mat.size << std::endl;
return 0;
}
在此示例中,创建了两个维度为 (3, 3, 3, 3) 的 4D Mat,然后使用该 hconcat 函数沿第二个维度连接起来。该 hconcat 函数的前两个参数是要连接的两个 Mats,第三个参数是输出 Mat。连接的新形状将是 (3, 6, 3, 3) 并且第二个 Mat 的信息将连接在第一个 Mat 的第二个维度中。 重要的是要注意输入 Mat 的维度必须相同,除了它们被连接的维度之外。此外,如果您想沿其他维度连接 Mat,则可以使用vconcat函数而不是hconcat.
将 4D Mat 按第二维度拆分
#include <opencv2/opencv.hpp>
int main()
{
// Create a 4D Mat with dimensions (3, 6, 3, 3)
cv::Mat mat(3, 6, 3, 3, CV_32F, cv::Scalar(0));
// Define the range of columns to slice
int start_col = 3;
int end_col = 6;
// Slice the Mat along the second dimension
cv::Mat sliced_mat = mat.colRange(start_col, end_col);
// Check the new shape of the sliced Mat
std::cout << "sliced_mat.dims: " << sliced_mat.dims << std::endl;
std::cout << "sliced_mat.size: " << sliced_mat.size << std::endl;
return 0;
}
在此示例中,创建了一个维度为 (3, 6, 3, 3) 的 4D Mat,然后使用该colRange方法沿第二个维度进行切片。该colRange方法的第一个参数是切片的起始列索引,第二个参数是切片的 结束列索引。在此示例中,Mat 被从第 3 列切片到第 6 列,从而产生了一个维度为 (3, 3, 3, 3) 的新 Mat。 请务必注意,该colRange方法仅沿第二个维度对 Mat 进行切片,如果您想沿其他维度对它进行切片,则可以改用rowRange、depth和channels方法。该Mat对象也是原始数据的视图,因此对切片 Mat 的任何更改也会影响原始 Mat。
将 4D Mat 按第三维度拆分
#include <opencv2/opencv.hpp>
int main()
{
// Create a 4D Mat with dimensions (3, 3, 6, 3)
cv::Mat mat(3, 3, 6, 3, CV_32F, cv::Scalar(0));
// Define the range of rows to slice
int start_row = 3;
int end_row = 6;
// Slice the Mat along the third dimension
cv::Mat sliced_mat = mat(cv::Range::all(), cv::Range::all(), cv::Range(start_row, end_row), cv::Range::all());
// Check the new shape of the sliced Mat
std::cout << "sliced_mat.dims: " << sliced_mat.dims << std::endl;
std::cout << "sliced_mat.size: " << sliced_mat.size << std::endl;
return 0;
}
在此示例中,创建了一个维度为 (3, 3, 6, 3) 的 4D Mat,然后使用该operator()方法沿第三个维度进行切片。该operator()方法的第一个参数是一个cv::Range对象,它定义了要切片的行的范围,在这个例子中它cv::Range::all()意味着所有行。第二个参数是另一个cv::Range对象,它定义了要切片的列的范围,在这个例子中它也是cv::Range::all(). 第三个参数是一个cv::Range对象,它定义了要切片的深度范围,在这个例子中,它cv::Range(start_row, end_row)表示第 3 到第 6 个深度。第四个参数是另一个cv::Range定义要切片的通道范围的对象,在本例中它也是cv::Range::all(). 新 Mat 的尺寸为 (3,3,3,3) 请务必注意,该 operator() 方法允许您沿任意维度对 Mat 进行切片,而且Mat对象是原始数据的视图,因此对切片 Mat 的任何更改也会影响原始 Mat。