我的标题可能还不够清楚,但请仔细查看以下描述。提前感谢。
我有一个RGB图像和二进制掩码图像:
Mat img = imread("test.jpg")
Mat mask = Mat::zeros(img.rows, img.cols, CV_8U);
给出掩模的一些,假设一个是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++;
}
}
}
,坐标将如下:在此处输入图像描述
但是,这两层的循环花费了太多时间。我想知道是否有一种更快的方法来奥丁颜色,希望你们能理解我要传达的内容。
ps:如果我可以使用python,则只能在一个句子中完成:
colors = img[mask == 1]
.at()
方法是访问C 中Mat
值的最慢方法。最快的是使用指针,但最佳实践是迭代器。请参阅有关扫描图像的OPENCV教程。
只是一个音符,即使Python的语法对这样的东西很好,它仍然必须在一天结束时循环遍历所有元素 - 而且由于它在此之前有一些开销比带指针的C 循环慢。无论您的图书馆如何,您都必须循环遍历所有元素,您正在与每个元素的面具进行比较。
如果您使用C 使用任何其他开源库灵活,请尝试Armadillo
。您可以使用它进行所有线性代数操作,而且,您可以将上述代码简化为一行(类似于您的Python代码段)。
或
尝试findNonZero()
功能,并在包含非零值的图像中找到所有坐标。检查以下内容:https://stackoverflow.com/a/19244484/7514664
启用了优化的编译,尝试分析此版本,并告诉我们它是否更快:
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]);
}
}
}
如果您知道颜色的大小,请事先预留其空间。