C++ 将cv::Mat转换为std::vector的通用函数

C++ 将cv::Mat转换为std::vector的通用函数,c++,opencv,templates,C++,Opencv,Templates,我想知道是否有一种通用方法可以将任何cv::Mat转换为std::vector。 对于特定类型,例如uchar,我可以: std::vector convert(常量cv::Ma&mat) { std::矢量阵列; if(mat.isContinuous()){ 分配(mat.data,mat.data+mat.total()); }否则{ 对于(int i=0;i 自动转换(常数矩阵和矩阵){ 使用T=typename Mat::value\u type::value\u type; cons

我想知道是否有一种通用方法可以将任何cv::Mat转换为std::vector。 对于特定类型,例如uchar,我可以:

std::vector convert(常量cv::Ma&mat)
{
std::矢量阵列;
if(mat.isContinuous()){
分配(mat.data,mat.data+mat.total());
}否则{
对于(int i=0;i
但是,我希望避免为不同的类型重复代码,并采用如下方式:

模板
标准::向量转换(常数cv::矩阵和矩阵)
{
std::矢量阵列;
if(mat.isContinuous()){
分配(mat.data,mat.data+mat.total());
}否则{
对于(int i=0;i
这不起作用,因为cv::Mat是在cv::Vec4f上模板化的。 当然我现在可以这样做了

模板
标准::向量转换(常数cv::矩阵和矩阵)

。。但为此,我收到一条错误消息:
注意:已忽略候选模板:无法将“Mat_uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

例如:

template<class Mat, std::enable_if_t<
         std::is_arithmetic_v<typename Mat::value_type>, int> = 0>
auto convert(const Mat& mat) {
    using T = typename Mat::value_type;
    std::vector<T> arr;
    // ...
    return arr;
}

template<class Mat, std::enable_if_t<
         std::is_arithmetic_v<typename Mat::value_type::value_type>, int> = 0>
auto convert(const Mat& mat) {
    using T = typename Mat::value_type::value_type;
    constexpr auto channels = typename Mat::value_type::channels; // = C
    std::vector<T> arr;
    // ...
    return arr;
}
template=0>
自动转换(常数矩阵和矩阵){
使用T=typename Mat::value\u type;
std::载体arr;
// ...
返回arr;
}
模板=0>
自动转换(常数矩阵和矩阵){
使用T=typename Mat::value\u type::value\u type;
constexpr auto channels=typename Mat::value_type::channels;//=C
std::载体arr;
// ...
返回arr;
}
第一个函数将接受带有任何算术
T
cv::Mat
。第二个将接受带有任何
T
cv::Mat
,使得
T::value\u type
是一个有效的算术类型(例如,
cv::Mat


如果需要,可以使用SFINAE添加更多约束。

标量矩阵和向量矩阵是不同的。你想如何将后者转换成向量?是的,这是事实,它们是不同的东西,但它们仍然可以被安排成大小为行*列*深度的标量的单个向量。所以你想“展平”向量矩阵?例如,你需要一个矩阵的推广吗?确切地说,我想把它展平。嗯,输入是矩阵的一种矩阵,如果我们把向量看作矩阵。你为什么这么问?有了模板,你可以写出一个非常通用的解决方案。所以我想知道你是否需要它,或者你唯一关心的类型是
cv::Mat\uz
。是的,这很有帮助。但它还没有完全起作用,因为我得到了一个“忽略的候选模板:替换失败[with Mat=cv::Mat]:在“cv::Mat”中没有名为“value\u type”的成员@Simon,对于
cv::Mat
您需要一个单独的重载,因为它没有
value\u type
成员类型
cv::Mat
cv::Mat\u
在这方面有很大的不同。@例如,Simon,您可以让第一个重载使用
cv::Mat
,第二个重载使用
cv::Mat\u
。第二个重载可以调用另一个有两个重载的函数,一个用于算术类型,另一个用于
cv::Vec
类型。@Simon,请注意,
cv::Mat
不能在
cv::Vec4f
上模板化@Simon您不能直接这样做。您需要有关元素类型(
T
)的其他信息
Mat
有一个
type()
成员函数,该函数将type作为
int
返回,这样
DataType::type
就等于它(
Mat
DataType::type
传递到构造函数内部的
Mat
)。您不能简单地“反转”
DataType
,因为
t
是编译时数量,而
type()
是运行时数量。您可以编写一些模板函数,并在一系列
if
语句中调用它,每个支持的数据类型对应一个。如果您对类型有一些限制,则可以对其进行合理的简化。