在opencv中查找熵

 Adonis-唯一 发布于 2023-02-12 23:48

我需要像entropyfilt()matlab 这样的函数,它在opencv中不存在.

在matlab中,J = entropyfilt(I)返回数组J,其中每个输出像素包含输入图像I中相应像素周围的9×9邻域的熵值.

我写了一个函数来用c ++实现它,foreach像素得到它的熵如下:

    使用cvCalHist适当设置的mask参数来获得图像ROI(这是一个9*9的矩形).

    归一化直方图,使其总和等于1.

    使用(香农)熵的公式.

我列出了下面的C++代码:

GetLocalEntroyImage( const IplImage*gray_src,IplImage*entopy_image){
    int hist_size[]={256};
    float gray_range[]={0,255};
    float* ranges[] = { gray_range};
    CvHistogram * hist = cvCreateHist( 1, hist_size, CV_HIST_SPARSE, ranges,1);
    for(int i=0;iwidth-1,i+4)-i);
                roi.height=(j-Max(0,j-4))+1+(Min(gray_src->height-1,j+4)-j);
                cvSetImageROI(const_cast(gray_src),roi);
                IplImage*gray_src_non_const=const_cast(gray_src);                            

                //2.calHist,here I chose CV_HIST_SPARSE to speed up
                cvCalcHist( &gray_src_non_const, hist, 0, 0 );*/
                cvNormalizeHist(hist,1.0);
                float total=0;
                float entroy=0;

               //3.get entroy
                CvSparseMatIterator it;
                for(CvSparseNode*node=cvInitSparseMatIterator((CvSparseMat*)hist-   >bins,&it);node!=0;node=cvGetNextSparseNode(&it)){
                float gray_frequency=*(float*)CV_NODE_VAL((CvSparseMat*)hist->bins,node);
                entroy=entroy-gray_frequency*(log(gray_frequency)/log(2.0f));//*(log(gray_frequency)/log(2.0))
                }
                ((float*)(local_entroy_image->imageData + j*local_entroy_image->widthStep))[i]=entroy;
                cvReleaseHist(&hist);
            }
        }
        cvResetImageROI(const_cast(gray_src));
    }

但是,代码太慢了.我在600*1200图像中测试它并且花费120秒,而在matlab中的entroyfilt只花费5秒.

有谁知道如何加快它或知道任何其他良好的实施

1 个回答
  • 你的代码中的大缓慢是这样的:log(gray_frequency)/log(2.0f)).

    你不应该打电话cvNormalizeHist().你知道垃圾箱的总和会达到81,所以只需81 * log(81)/log(2)从计算的熵中减去(但当然这是一个常数,不是每次在你的循环中计算).如果你没有规范化hisgram,它的条目将是整数,你可以使用它们来访问查找表.

    由于您有一个9x9内核,因此最大值gray_frequency为81(只要您不对直方图进行标准化),您可以log()通过单个查找预先计算的表轻松替换这两个调用.这将产生巨大的差异.您可以像这样初始化表:

        double entropy_table[82]; // 0 .. 81
        const double log2 = log(2.0);
        entropy_table[0] = 0.0;
        for(int i = 1; i < 82; i ++)
        {
            entropy_table[i] = i * log(double(i)) / log2;
        }
    

    然后它只是:

    entroy -= entropy_table[gray_frequency];
    

    您也可以发现实现自己的histgram代码是一个胜利.例如,如果你有一个小内核,你可以跟踪你将使用哪些垃圾箱,只清除它们.但由于你使用的是81/256垃圾箱,这可能不值得.

    另一个你可以加速的地方是borrder像素处理.您正在检查每个像素.但是如果你为边界像素和内部像素设置了单独的循环,则可以避免大量的max和min调用.

    如果仍然不够快,您可以考虑在条纹上使用parallel_for.作为如何做到这一点的一个很好的例子,看看OpenCV的形态滤波器的源代码.

    2023-02-13 00:37 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有