问题描述
在OpenCV> = 3.0中逐步通过OpenCV Mat时,这是一个普遍的问题
目前,对于OpenCV Mat的每种数据类型(32F,8U,64F,16S),我都有几乎复制粘贴的功能。这不是很好,因为如果我想更改任何内容,则必须在所有4个功能中都进行更改。
uchar* imPtr = (uchar*)A.data;
uchar max=0,dummy;
for (int i = 0; i < A.rows; i++)
{
const uchar* Mi = A.ptr<uchar>(i);
for (int j = 0; j < A.cols; j++)
{
dummy = Mi[j];
if (dummy > max)
{
max = dummy;
}
}
}
return max;
如果要为4种数据类型编写此代码,则需要使用(double ),(float ),(int )和(uchar )。有没有做类似(auto *)之类的好方法?
解决方法
请考虑使用Mat_
类模板而不是Mat
。使用Mat_
,您可以在编译时知道类型,并且很容易将函数重写为类型安全的函数模板:
template<class T>
T Max(cv::Mat_<T>& A) {
T* imPtr = (T*)A.data;
T max = 0,dummy;
for (int i = 0; i < A.rows; i++) {
const T* Mi = A.ptr<T>(i);
for (int j = 0; j < A.cols; j++) {
dummy = Mi[j];
if (dummy > max)
max = dummy;
}
}
return max;
}
cv::Mat_<uint8_t> mat1 = (cv::Mat_<uint8_t>(2,2) << 1,2,3,4);
std::cout << (int)Max(mat1) << std::endl; // 4
cv::Mat_<float> mat2 = (cv::Mat_<float>(2,2) << 4,12,11);
std::cout << Max(mat2) << std::endl; // 12
您可以继续使用cv::Mat
,但随后必须明确指定所需的类型:
template<class T>
T Max2(cv::Mat& A) {
T* imPtr = (T*)A.data;
T max = 0,dummy;
for (int i = 0; i < A.rows; i++) {
const T* Mi = A.ptr<T>(i);
for (int j = 0; j < A.cols; j++) {
dummy = Mi[j];
if (dummy > max)
max = dummy;
}
}
return max;
}
short data[] = { 1,1 };
cv::Mat mat3(2,CV_16SC1,data);
std::cout << Max2<short>(mat3) << std::endl; // 3
但是使用此版本,很容易产生错误,例如,如果使用T
构造int
时将Mat
指定为CV_32FC1
-find max将截断将所有浮点数都加到int
,这将导致返回错误的结果。