Opencv obatin基于掩模的某些像素RGB值

时间:2017-09-21 09:28:42

标签: c++ opencv

我的标题可能不够明确,但请仔细阅读以下说明。谢谢。

我有一个RGB图像和二进制掩码图像:

Mat img = imread("test.jpg")
Mat mask = Mat::zeros(img.rows, img.cols, CV_8U);

给掩码一些,假设1的个数是N.现在非零坐标是已知的,基于这些坐标,我们可以肯定地获得原始图像的相应像素RGB值。我知道这可以完成通过以下代码:

Mat colors = Mat::zeros(N, 3, CV_8U);
int counter = 0;
for (int i = 0; i < mask.rows; i++)
{
    for (int j = 0; j < mask.cols; j++)
    {
        if (mask.at<uchar>(i, j) == 1)
        {
            colors.at<uchar>(counter, 0) = img.at<Vec3b>(i, j)[0];
            colors.at<uchar>(counter, 1) = img.at<Vec3b>(i, j)[1];
            colors.at<uchar>(counter, 2) = img.at<Vec3b>(i, j)[2];
            counter++;
        }
    }
}

和弦如下: enter image description here

然而,这两层for循环花费了太多时间。我想知道是否有更快的方法来观察颜色,希望你们能理解我想传达的内容。

PS:如果我可以使用python,这只能用一句话来完成:

colors = img[mask == 1]

3 个答案:

答案 0 :(得分:1)

如果您可以灵活地使用C ++使用任何其他开源库,请尝试 al_menu.size() // it always give you size of folder, al_menu.get(int_position).getAl_imagepath().size(); // passing the folder position so that correct folder images are to be shown. public TouchImageAdapter(Context context,ArrayList<Model_images> al_menu, int position){ this.al_menu = al_menu; this.context = context; this.int_position = position; } @Override public int getCount() { return al_menu.get(int_position).getAl_imagepath().size(); } 。您可以使用它执行所有线性代数运算,并且还可以将上面的代码减少到一行(类似于您的Python代码段)。

或者

尝试Armadillo函数,找到包含非零值的图像中的所有坐标。检查一下:https://stackoverflow.com/a/19244484/7514664

答案 1 :(得分:1)

.at()方法是在C ++中访问Mat值的最慢方法。最快的是使用指针,但最佳实践是迭代器。请参阅OpenCV tutorial on scanning images

请注意,即使Python的语法很适合这样的事情,它仍然必须在一天结束时遍历所有元素 - 并且因为它在此之前有一些开销,所以它是事实上的比带有指针的C ++循环慢。无论你的库是什么,你都需要循环遍历所有元素,你正在与每个元素的掩码进行比较。

答案 2 :(得分:0)

在启用优化的情况下进行编译,尝试分析此版本并告诉我们它是否更快:

vector<Vec3b> colors;
if (img.isContinuous() && mask.isContinuous()) {
    auto pimg = img.ptr<Vec3b>();
    for (auto pmask = mask.datastart; pmask < mask.dataend; ++pmask, ++pimg) {
        if (*pmask)
            colors.emplace_back(*pimg);
    }
}
else {
    for (int r = 0; r < img.rows; ++r) {
        auto prowimg = img.ptr<Vec3b>(r);
        auto prowmask = img.ptr(r);
        for (int c = 0; c < img.cols; ++c) {
            if (prowmask[c])
                colors.emplace_back(prowimg[c]);
        }
    }
}

如果您知道颜色的大小,请事先为其预留空间。