在OpenCV中复制像素值

Duplicating pixel values in OpenCV

本文关键字:像素 复制 OpenCV      更新时间:2023-10-16

我有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。

可以使用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在评论中指出这一点。

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

下面的代码将生成您的确切输出:

#include <opencv2opencv.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;
}

我会使用OpenCV Repeat函数,它比最近邻调整大小更快(更可读)。