如何以优雅的方式使用 OpenCV、c++ 检索偶数/奇数索引中的值?

Posted

技术标签:

【中文标题】如何以优雅的方式使用 OpenCV、c++ 检索偶数/奇数索引中的值?【英文标题】:How to retrieve values in even/odd indices using OpenCV, c++ in an elegant way? 【发布时间】:2016-04-13 00:54:20 【问题描述】:

考虑一下,我有以下矩阵

0   1  2  3  
4   5  6  7  
8   9 10 11  
12 13 14 15  

我想在不使用 for 循环的情况下检索偶数索引中的值(x 和 y 索引都是偶数)。

0  2
8 10

我有大尺寸的图像(许多 5000*5000+ 灰度矩阵)。使用 for 循环似乎不是最好的方法。我想知道是否有比 for 循环更好的方法。

我尝试使用以下掩码,然后执行操作,但效率不高,因为我需要进行 4*n^2 乘法而不是 n^2(假设原始图像为 2n*2n)

1 0 1 0
0 0 0 0
1 0 1 0
0 0 0 0

请注意,我对矩阵进行了多次操作。任何帮助表示赞赏。

提前致谢,

【问题讨论】:

【参考方案1】:

您可以删除无用的行和列,并处理一个大小为原始矩阵一半的矩阵。

您可以使用resize 函数轻松完成此操作,并使用最接近的插值:

    #include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;

int main(int argc, char **argv)

    Mat1b mat = (Mat1b(4,4) << 0, 1, 2, 3,
                               4, 5, 6, 7,
                               8, 9, 10, 11, 
                               12, 13, 14, 15);

    Mat1b res;
    resize(mat, res, Size(0, 0), 0.5, 0.5, INTER_NEAREST);

    cout << "Mat:" << endl << mat << endl << endl;
    cout << "Res:" << endl << res << endl;

    return 0;

那么res 中的值只是您需要的索引处的值:

Mat:
[0, 1, 2, 3;
 4, 5, 6, 7;
 8, 9, 10, 11;
 12, 13, 14, 15]

Res:
[0, 2;
 8, 10]

为了将值恢复到原始位置,您可以使用具有合适模式的 Kronecker 产品(在 OpenCV 中不可用,但可以是 easily implemented)。这将产生:

Mat:
[0, 1, 2, 3;
 4, 5, 6, 7;
 8, 9, 10, 11;
 12, 13, 14, 15]

Res:
[0, 2;
 8, 10]

Res Modified:
[1, 3;
 9, 11]

Restored:
[1, 0, 3, 0;
 0, 0, 0, 0;
 9, 0, 11, 0;
 0, 0, 0, 0]

代码:

#include <opencv2/opencv.hpp>
#include <algorithm>
#include <iostream>
using namespace cv;
using namespace std;

Mat kron(const Mat A, const Mat B)

    CV_Assert(A.channels() == 1 && B.channels() == 1);

    Mat1d Ad, Bd;
    A.convertTo(Ad, CV_64F);
    B.convertTo(Bd, CV_64F);

    Mat1d Kd(Ad.rows * Bd.rows, Ad.cols * Bd.cols, 0.0);

    for (int ra = 0; ra < Ad.rows; ++ra)
    
        for (int ca = 0; ca < Ad.cols; ++ca)
        
            Kd(Range(ra*Bd.rows, (ra + 1)*Bd.rows), Range(ca*Bd.cols, (ca + 1)*Bd.cols)) = Bd.mul(Ad(ra, ca));
        
    
    Mat K;
    Kd.convertTo(K, A.type());
    return K;




int main(int argc, char **argv)

    Mat1b mat = (Mat1b(4, 4) << 0, 1, 2, 3,
        4, 5, 6, 7,
        8, 9, 10, 11,
        12, 13, 14, 15);

    Mat1b res;
    resize(mat, res, Size(0, 0), 0.5, 0.5, INTER_NEAREST);

    cout << "Mat:" << endl << mat << endl << endl;
    cout << "Res:" << endl << res << endl << endl;

    // Work on Res
    res += 1;

    cout << "Res Modified:" << endl << res << endl << endl;

    // Define the pattern
    Mat1b pattern = (Mat1b(2,2) << 1, 0, 
                                   0, 0);

    // Apply Kronecker product
    Mat1b restored = kron(res, pattern);

    cout << "Restored:" << endl << restored << endl << endl;

    return 0;

【讨论】:

让我想知道这是否是 OP 的初衷?一点***的重新发明从来没有伤害过任何人:) 非常感谢。这是一个非常好的解决方案。如果我能够以某种方式获得一个只有索引 [0,2;8,10] 非零的 4*4 矩阵,那么其余的都是零。例如在其他操作res = [1, 9; 5, 7]; 之后,我想在 4*4 矩阵中的位置获取这些值,其余的为零。最新的矩阵将是[1,0,9,0; 0,0,0,0; 5,0,7,0; 0,0,0,0]。这肯定会加快速度,但我有点贪心:) @sm 我不明白,请您详细说明一下吗? 我会用res做一些操作,然后我想放大到原来的大小(4*4)。 res 的值将在其原始索引中,矩阵的其余部分将为零。在我们的 4*4 示例中,索引 (0,0),(0,2),(2,0),(2,2) 将是 res 的最终值,而其他像素将为零。

以上是关于如何以优雅的方式使用 OpenCV、c++ 检索偶数/奇数索引中的值?的主要内容,如果未能解决你的问题,请参考以下文章

Opencv 函数只能以 C 代码方式调用,但不能以 C++ 方式调用

我可以以任何方式从 OpenCV 对象取消引用中将数据分配给双重函数返回检索吗?

如何将 C++ 数组转换为 opencv Mat

检索 MySQL 表注释的最优雅方法是啥?

如何将 opencv c++ 代码集成到使用 c# 以统一 3D 开发的移动应用程序中

如何在 OpenCV 和 C++ 中配置 CvSVM 以进行图像分类