2

我有大约 20 张经过颜色编码的图像。我想扫描每个图像并将像素与与该颜色关联的标签匹配。我已经编写了下面的代码,但是运行这个看似简单的任务大约需要 30 分钟。图像的分辨率为 960 x 720。

我的代码:

void go_through_pixels(path &image_dir, string& ground_truth_suffix, string image_format, unordered_map<RGB, string> colors_for_labels){

    if(!exists(image_dir)){
        cerr << image_dir << " does not exist, prematurely returning" << endl;
        exit(-1);
    }

    unordered_map<string, set<path> > label_to_files_map;

    //initialise label_to_files_map
    for(unordered_map<RGB, string>::iterator it = colors_for_labels.begin(); it != colors_for_labels.end(); it++){
        label_to_files_map[it->second] = set<path>();
    }

    directory_iterator end_itr; //default construction provides an end reference

    for(directory_iterator itr(image_dir); itr != end_itr; itr++){

        path file = itr->path();
        string filename = file.filename().string();
        RGB rgb(0,0,0); //default rgb struct, values will be changed in the loop

        if(extension(file) == image_format && filename.find(ground_truth_suffix) != string::npos){
            //ground truth file
            Mat img = imread(file.string(), CV_LOAD_IMAGE_COLOR);

            for(int y = 0; y < img.rows; y++){
                for(int x = 0; x < img.cols; x++){
                    //gives data as bgr instead of rgb
                    Point3_<uchar>* pixel = img.ptr<Point3_<uchar> >(y,x);
                    rgb.red = (int)pixel->z;
                    rgb.green = (int)pixel->y;
                    rgb.blue =(int)pixel->x;
                    string label = colors_for_labels[rgb];
                    label_to_files_map[label].insert(file);
                    cout << label << endl;
                }
            }
        }
    }
}

之后我会用这些数据做更多的事情,但我已经将我的代码简化到这个只是为了尝试找出性能问题。

我发现这label_to_files_map[label].insert(file)是导致大部分延迟的原因,因为删除后只需扫描图像大约需要 3 分钟。我仍然认为这太长了,但可能是错的?

此外,由于该集合insert需要很长时间(因为它必须在插入之前检查重复项),任何人都可以建议在这里使用更好的数据结构吗?

本质上,一张图片可以有 100 个像素对应于建筑物,100 个像素对应于汽车等等,所以我只想在地图label_to_files_map中记录这个文件(正在扫描的当前图像)里面有一个建筑物(在这个case 由特定的 rgb 值表示)。

4

3 回答 3

3

性能问题是您在每个像素上做了太多的工作。

对于每个文件(就在您的堆叠 for 循环开始之前)制作 color_for_labels 的副本。

        Point3_<uchar> oldPixel;
        for(int y = 0; y < img.rows; y++){
            for(int x = 0; x < img.cols; x++){
                //gives data as bgr instead of rgb
                Point3_<uchar>* pixel = img.ptr<Point3_<uchar> >(y,x);
                if(*pixel == oldPixel) 
                    continue; // skip extra work
                oldPixel = *pixel
                rgb.red = (int)pixel->z;
                rgb.green = (int)pixel->y;
                rgb.blue =(int)pixel->x;
                string label = copy_of_colors_for_labels[rgb];
                if(label != null) {
                    label_to_files_map[label].insert(file);
                    copy_of_colors_for_labels[rgb] = null;
                    cout << label << endl;
                }
            }
        }

可能存在语法错误(因为我在浏览器中重新编写了它,并且多年没有用 C++ 编写代码),但以上内容应该消除了很多额外的处理工作。

于 2012-10-09T17:23:54.253 回答
1

您使用了错误的数据类型和错误的函数。这里有一个关于如何改进的建议。我想它会在几秒钟内运行。

您工作的第 1 步是从 3 通道图像到单通道图像的查找表。你可以使用 cv::LUT。但是,您需要做一个技巧以使其快速。

将其转换为每像素 4 个字节:

cv::Mat mat4bytes;
// add 8 bits to each pixel. the fill value is 255
cv::cvtColor(img, mat4bytes, CV_RGB2RGBA); 
// this is a nice hack to interpret 
// the RGBA pixels of the input image as integers 
cv::Mat pseudoInteger(img.size(), CV_32UC1, mat4bytes.data);

现在,您可以应用 LUT。

cv::Mat colorCoded;
// you have to convert your colors_for_labels lookup table
// like this: 
lookupTable[i] = 
      ((unsigned int)colors_for_labels.first.x << 24 ) + 
      ((unsigned int)colors_for_labels.first.y << 16 ) +        
      ((unsigned int)colors_for_labels.first.z << 8  ) +        
      255; 
// make sure it is correct!!!
// and lookupTable data MUST be unsigned integer

cv::LUT(pseudoInteger, colorCoded, lookupTable);

编辑此时你在lookupTable中有你计算的值label

计算的最后一步实际上是直方图。那么为什么不使用 OpenCV 的直方图函数呢?检查文档calcHist(),看看它如何最适合您的算法。请注意,calcHist()可以一次执行更多图像的直方图,因此您可能希望将colorCoded图像保存在矢量中,然后将所有图像的直方图提取到一个中。

于 2012-10-09T18:01:05.760 回答
0

除了关于代码优化的其他答案,考虑处理图像直方图。图像中的几个像素将具有完全相同的颜色,因此首先计算直方图,然后对图像中的每种不同颜色进行处理。那应该大大加快速度

于 2012-10-10T14:30:33.967 回答