对OpenCV中的merge/split函数进行了实现,经测试,与OpenCV3.1结果完全一致。
merge实现代码merge.hpp:
// fbc_cv is free software and uses the same licence as OpenCV // Email: [email protected] #ifndef FBC_CV_MERGE_HPP_ #define FBC_CV_MERGE_HPP_ /* reference: include/opencv2/core.hpp core/src/convert.cpp core/src/merge.cpp */ #include <vector> #include "core/mat.hpp" #ifndef __cplusplus #error merge.hpp header must be compiled as C++ #endif namespace fbc { // merge several arrays to make a single multi-channel array template<typename _Tp, int chs1, int chs2> int merge(const std::vector<Mat_<_Tp, chs1>>& src, Mat_<_Tp, chs2>& dst) { FBC_Assert(dst.data != NULL); FBC_Assert((src.size() > 0) && (src.size() == dst.channels) && (src.size() <= FBC_CN_MAX)); int width = src[0].cols; int height = src[0].rows; FBC_Assert((dst.cols == width) && (dst.rows == height)); for (int i = 0; i < src.size(); i++) { FBC_Assert(src[i].data != NULL); FBC_Assert((src[i].cols == width) && src[i].rows == height); FBC_Assert(src[i].channels == 1); } if (src.size() == 1) { memcpy(dst.data, src[0].data, dst.step * dst.rows); return 0; } _Tp* pDst = (_Tp*)dst.data; int len = width * height; int cn = dst.channels; for (int i = 0; i < src.size(); i++) { _Tp* pSrc = (_Tp*)src[i].data; for (int j = 0; j < len; j++) { pDst[j * cn + i] = pSrc[j]; } } return 0; } } // namespace fbc #endif // FBC_CV_MERGE_HPP_split实现代码split.hpp:
// fbc_cv is free software and uses the same licence as OpenCV // Email: [email protected] #ifndef FBC_CV_SPLIT_HPP_ #define FBC_CV_SPLIT_HPP_ /* reference: include/opencv2/core.hpp core/src/convert.cpp core/src/split.cpp */ #include <vector> #include "core/mat.hpp" #ifndef __cplusplus #error split.hpp header must be compiled as C++ #endif namespace fbc { // split a multi-channel array into separate single-channel arrays template<typename _Tp, int chs1, int chs2> int split(const Mat_<_Tp, chs1>& src, std::vector<Mat_<_Tp, chs2>>& dst) { FBC_Assert(src.data != NULL); FBC_Assert((dst.size() == chs1) && (chs2 == 1)); for (int i = 0; i < dst.size(); i++) { FBC_Assert((dst[i].data != NULL) && (dst[i].rows == src.rows) && (dst[i].cols == src.cols)); } int cn = src.channels; if (cn == 1) { memcpy(dst[0].data, src.data, src.step * src.rows); return 0; } _Tp* pSrc = (_Tp*)src.data; int len = src.rows * src.cols; for (int i = 0; i < cn; i++) { _Tp* pDst = (_Tp*)dst[i].data; for (int j = 0; j < len; j++) { pDst[j] = pSrc[j * cn + i]; } } return 0; } } // namespace fbc #endif // FBC_CV_SPLIT_HPP_merge测试代码:
#include <assert.h> #include <vector> #include <core/mat.hpp> #include <merge.hpp> #include <opencv2/opencv.hpp> #include "test_merge.hpp" int test_merge_uchar() { cv::Mat matSrc1 = cv::imread("E:/GitCode/OpenCV_Test/test_images/lena.png", 1); cv::Mat matSrc2 = cv::imread("E:/GitCode/OpenCV_Test/test_images/1.jpg", 1); cv::Mat matSrc3 = cv::imread("E:/GitCode/OpenCV_Test/test_images/2.jpg", 1); if (!matSrc1.data || !matSrc2.data || !matSrc3.data) { std::cout << "read image fail" << std::endl; return -1; } int width = 500, height = 600; cv::cvtColor(matSrc1, matSrc1, CV_BGR2GRAY); cv::cvtColor(matSrc2, matSrc2, CV_BGR2GRAY); cv::cvtColor(matSrc3, matSrc3, CV_BGR2GRAY); cv::resize(matSrc1, matSrc1, cv::Size(width, height)); cv::resize(matSrc2, matSrc2, cv::Size(width, height)); cv::resize(matSrc3, matSrc3, cv::Size(width, height)); fbc::Mat_<fbc::uchar, 1> mat1(height, width, matSrc1.data); fbc::Mat_<fbc::uchar, 1> mat2(height, width, matSrc2.data); fbc::Mat_<fbc::uchar, 1> mat3(height, width, matSrc3.data); std::vector<fbc::Mat_<fbc::uchar, 1>> mat; mat.push_back(mat1); mat.push_back(mat2); mat.push_back(mat3); fbc::Mat_<fbc::uchar, 3> matDst(height, width); fbc::merge(mat, matDst); std::vector<cv::Mat> mat_; mat_.push_back(matSrc1); mat_.push_back(matSrc2); mat_.push_back(matSrc3); cv::Mat matDst_; cv::merge(mat_, matDst_); assert(matDst.channels == matDst_.channels()); assert((matDst.rows == matDst_.rows) && (matDst.cols == matDst_.cols)); assert(matDst.step == matDst_.step); for (int i = 0; i < matDst.rows; i++) { const fbc::uchar* p1 = matDst.ptr(i); const uchar* p2 = matDst_.ptr(i); for (int j = 0; j < matDst.step; j++) { assert(p1[j] == p2[j]); } } return 0; } int test_merge_float() { cv::Mat matSrc1 = cv::imread("E:/GitCode/OpenCV_Test/test_images/lena.png", 1); cv::Mat matSrc2 = cv::imread("E:/GitCode/OpenCV_Test/test_images/1.jpg", 1); cv::Mat matSrc3 = cv::imread("E:/GitCode/OpenCV_Test/test_images/2.jpg", 1); if (!matSrc1.data || !matSrc2.data || !matSrc3.data) { std::cout << "read image fail" << std::endl; return -1; } int width = 500, height = 600; cv::cvtColor(matSrc1, matSrc1, CV_BGR2GRAY); cv::cvtColor(matSrc2, matSrc2, CV_BGR2GRAY); cv::cvtColor(matSrc3, matSrc3, CV_BGR2GRAY); cv::resize(matSrc1, matSrc1, cv::Size(width, height)); cv::resize(matSrc2, matSrc2, cv::Size(width, height)); cv::resize(matSrc3, matSrc3, cv::Size(width, height)); matSrc1.convertTo(matSrc1, CV_32FC1); matSrc2.convertTo(matSrc2, CV_32FC1); matSrc3.convertTo(matSrc3, CV_32FC1); fbc::Mat_<float, 1> mat1(height, width, matSrc1.data); fbc::Mat_<float, 1> mat2(height, width, matSrc2.data); fbc::Mat_<float, 1> mat3(height, width, matSrc3.data); std::vector<fbc::Mat_<float, 1>> mat; mat.push_back(mat1); mat.push_back(mat2); mat.push_back(mat3); fbc::Mat_<float, 3> matDst(height, width); fbc::merge(mat, matDst); std::vector<cv::Mat> mat_; mat_.push_back(matSrc1); mat_.push_back(matSrc2); mat_.push_back(matSrc3); cv::Mat matDst_; cv::merge(mat_, matDst_); assert(matDst.channels == matDst_.channels()); assert((matDst.rows == matDst_.rows) && (matDst.cols == matDst_.cols)); assert(matDst.step == matDst_.step); for (int i = 0; i < matDst.rows; i++) { const fbc::uchar* p1 = matDst.ptr(i); const uchar* p2 = matDst_.ptr(i); for (int j = 0; j < matDst.step; j++) { assert(p1[j] == p2[j]); } } return 0; }split测试代码:
#include <assert.h> #include <vector> #include <core/mat.hpp> #include <split.hpp> #include <opencv2/opencv.hpp> #include "test_split.hpp" int test_split_uchar() { cv::Mat mat = cv::imread("E:/GitCode/OpenCV_Test/test_images/lena.png", 1); if (!mat.data) { std::cout << "read image fail" << std::endl; return -1; } //cv::cvtColor(mat, mat, CV_BGR2GRAY); int chs = mat.channels(); int width = mat.cols; int height = mat.rows; fbc::Mat_<fbc::uchar, 3> mat1(height, width, mat.data); std::vector<fbc::Mat_<fbc::uchar, 1>> vecMat2; fbc::Mat_<fbc::uchar, 1>* mat2 = new fbc::Mat_<fbc::uchar, 1>[chs]; for (int i = 0; i < chs; i++) { mat2[i] = fbc::Mat_<fbc::uchar, 1>(height, width); vecMat2.push_back(mat2[i]); } fbc::split(mat1, vecMat2); cv::Mat mat1_(height, width, CV_8UC3, mat.data); std::vector<cv::Mat> vecMat2_; cv::split(mat1_, vecMat2_); assert(vecMat2.size() == vecMat2_.size()); for (int i = 0; i < vecMat2.size(); i++) { assert(vecMat2[i].rows == vecMat2_[i].rows && vecMat2[i].cols == vecMat2_[i].cols); assert(vecMat2[i].step == vecMat2_[i].step); assert(vecMat2[i].channels == vecMat2_[i].channels()); for (int y = 0; y < vecMat2[i].rows; y++) { const fbc::uchar* p = vecMat2[i].ptr(y); const uchar* p_ = vecMat2_[i].ptr(y); for (int x = 0; x < vecMat2[i].step; x++) { assert(p[x] == p_[x]); } } } delete[] mat2; return 0; } int test_split_float() { cv::Mat mat = cv::imread("E:/GitCode/OpenCV_Test/test_images/lena.png", 1); if (!mat.data) { std::cout << "read image fail" << std::endl; return -1; } mat.convertTo(mat, CV_32FC3); //cv::cvtColor(mat, mat, CV_BGR2GRAY); int chs = mat.channels(); int width = mat.cols; int height = mat.rows; fbc::Mat_<float, 3> mat1(height, width, mat.data); std::vector<fbc::Mat_<float, 1>> vecMat2; fbc::Mat_<float, 1>* mat2 = new fbc::Mat_<float, 1>[chs]; for (int i = 0; i < chs; i++) { mat2[i] = fbc::Mat_<float, 1>(height, width); vecMat2.push_back(mat2[i]); } fbc::split(mat1, vecMat2); cv::Mat mat1_(height, width, CV_32FC3, mat.data); std::vector<cv::Mat> vecMat2_; cv::split(mat1_, vecMat2_); assert(vecMat2.size() == vecMat2_.size()); for (int i = 0; i < vecMat2.size(); i++) { assert(vecMat2[i].rows == vecMat2_[i].rows && vecMat2[i].cols == vecMat2_[i].cols); assert(vecMat2[i].step == vecMat2_[i].step); assert(vecMat2[i].channels == vecMat2_[i].channels()); for (int y = 0; y < vecMat2[i].rows; y++) { const fbc::uchar* p = vecMat2[i].ptr(y); const uchar* p_ = vecMat2_[i].ptr(y); for (int x = 0; x < vecMat2[i].step; x++) { assert(p[x] == p_[x]); } } } delete[] mat2; return 0; }