【问题标题】:Duplicating pixel values in OpenCV在 OpenCV 中复制像素值
【发布时间】:2019-09-12 19:08:54
【问题描述】:

我有 RGB 图像,例如大小为 2x2 如下:

[  0,  14, 255,  75, 156, 255;
  45, 255, 234, 236, 141, 255]

我想将每个像素(所有 RGB 通道)复制 2x2 次并获得如下所示的图像:

[  0,  14, 255,  0, 14, 255,  75, 156, 255, 75, 156, 255;
   0,  14, 255,  0, 14, 255,  75, 156, 255, 75, 156, 255;
  45, 255, 234,  45, 255, 234, 236, 141, 255, 236, 141, 255;
  45, 255, 234,  45, 255, 234, 236, 141, 255, 236, 141, 255  ]

在 Matlab 或 Python 中,我只需使用 kron 函数即可完成此操作,但我无法弄清楚如何在 OpenCV C++ 中轻松完成此操作。请注意,这是一个简单的示例,我实际上希望将每个像素复制 16x16 并在更大的图像上执行此操作,当然不是 2x2。

【问题讨论】:

  • 我认为 cv::resize 与插值 INTER_NEAREST 会成功。找到了一个similar question 证实了调整大小的想法。虽然,我还没有尝试/使用过这种插值。
  • 你能发布一下你在 Matlab 中是如何做到这一点的吗?
  • 嗨@Miki,Matlab 是什么意思?我虽然你的问题是如何使用 OpenCV 和 C++ 来做到这一点。无论如何,我只是在这里尝试过,它可以工作。我使用命令 cv::resize(m, enlarged, cv::Size(m.rows*20, m.cols*20), 20, 20, cv::INTER_NEAREST); 将大小调整为 20 倍(这样我可以查看并验证结果)。
  • @wendelbsilva 我在问 OP 他将如何在 Matlab 中做到这一点......
  • 操作.. 我的错。我以为你是 Op.

标签: c++ opencv


【解决方案1】:

您可以使用resize 和最近邻插值INTER_NEAREST

代码:

Mat mInput(2, 2, CV_8UC3),mOutput(4, 4, CV_8UC3);

mInput.at<Vec3b>(0,0)= Vec3b(0,14,255);
mInput.at<Vec3b>(0,1)= Vec3b(75,156,255);
mInput.at<Vec3b>(1,0)= Vec3b(45,255,234);
mInput.at<Vec3b>(1,1)= Vec3b(236,141,255);

cout<<mInput<<"\n";

resize(mInput,mOutput,Size(4,4),0,0,INTER_NEAREST);

cout<<mOutput<<"\n";;    

输出

[  0,  14, 255,  75, 156, 255;
  45, 255, 234, 236, 141, 255]
[  0,  14, 255,   0,  14, 255,  75, 156, 255,  75, 156, 255;
   0,  14, 255,   0,  14, 255,  75, 156, 255,  75, 156, 255;
  45, 255, 234,  45, 255, 234, 236, 141, 255, 236, 141, 255;
  45, 255, 234,  45, 255, 234, 236, 141, 255, 236, 141, 255]
Press any key to continue . . .

感谢 @wendelbsilva 在 cmets 中指出这一点。

【讨论】:

  • 我用更大的图像和更大的调整大小进行了测试。只要您在resize 中提供正确的大小,此方法就可以正常工作。你总能学到新东西:D 好电话
  • 太棒了!我不知道resize有这样的选择。
【解决方案2】:

您可以包装kron 函数并像在Matlab 和Python 中那样做。请注意,Kronecker 积是在单通道矩阵上定义的,因此您需要拆分平面 BGR 矩阵,应用kron,然后合并回来。

以下代码将产生您的确切输出:

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

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()
{
    Mat3d A(2,2);
    A(0, 0) = Vec3d(0, 14, 255);
    A(0, 1) = Vec3d(75, 156, 255);
    A(1, 0) = Vec3d(45, 255, 234);
    A(1, 1) = Vec3d(236, 141, 255);

    cout << "A:" << endl;
    cout << A << endl;

    Mat1d B = Mat1d::ones(2,2);

    cout << "B:" << endl;
    cout << B << endl;

    vector<Mat> planes;
    split(A, planes);

    for (int i = 0; i < 3; ++i)
    {
        planes[i] = kron(planes[i], B);
    }

    Mat K;
    merge(planes, K);

    cout << "K:" << endl;
    cout << K << endl;


    return 0;
}

【讨论】:

    【解决方案3】:

    我只会使用OpenCV Repeat function,它比使用最近的邻居调整大小更快(并且更具可读性)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-14
      • 2021-05-05
      • 2015-09-01
      • 2018-12-12
      • 1970-01-01
      • 1970-01-01
      • 2012-02-24
      • 2021-12-10
      相关资源
      最近更新 更多