OpenCVコード抽出:merge/split関数の実装
9648 ワード
OpenCVの中のmerge/split関数を実現して、テストして、OpenCV 3と.1結果は完全に一致した.
merge実装コードmerge.hpp:
split実装コードsplit.hpp:
mergeテストコード:
splitテストコード:
GitHub: https://github.com/fengbingchun/OpenCV_Test
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;
}
GitHub: https://github.com/fengbingchun/OpenCV_Test