gpt4 book ai didi

matlab - 在opencv中寻找熵

转载 作者:太空宇宙 更新时间:2023-11-03 19:39:19 24 4
gpt4 key购买 nike

我需要一个类似 matlab 中的 entropyfilt() 的函数,它在 opencv 中不存在。

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

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

  1. 使用 cvCalHist 并适当设置掩码参数以获得图像 ROI(这是一个 9*9 的矩形)。
  2. 标准化直方图,使其 bin 的总和等于 1。
  3. 使用(香农)熵的公式。

我在下面列出了 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;i<gray_src.width;i++){
for(int j=0;j<gray_src.height;j++){
//calculate entropy for pixel(i,j)
//1.set roi rect(9*9),handle edge pixel
CvRect roi;
int threshold=Max(0,i-4);
roi.x=threshold;
threshold=Max(0,j-4);
roi.y=threshold;
roi.width=(i-Max(0,i-4))+1+(Min(gray_src->width-1,i+4)-i);
roi.height=(j-Max(0,j-4))+1+(Min(gray_src->height-1,j+4)-j);
cvSetImageROI(const_cast<IplImage*>(gray_src),roi);
IplImage*gray_src_non_const=const_cast<IplImage*>(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<IplImage*>(gray_src));
}

但是,代码太慢了。我在600*1200的图片上测试了120s,而matlab中的entroyfilt只需要5s。

有谁知道如何加速它或知道任何其他好的实现

最佳答案

您的代码中最慢的是:log(gray_frequency)/log(2.0f))

您不应调用 cvNormalizeHist()。您知道 bin 的总和为 81,因此只需从计算的熵中减去 81 * log(81)/log(2)(当然,这是一个常数,并非每次都在您的计算中计算)环形)。如果您不规范化直方图,它的条目将是整数,您可以使用它们来访问查找表。

因为你有一个 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];

此外,您可能会发现实现自己的直方图代码是一种成功。例如。如果你有一个小内核,你可以跟踪你将要使用的垃圾箱,并且只清除那些垃圾箱。但由于您使用的是 81/256 箱,这可能不值得。

另一个可以加快速度的地方是边界像素处理。您正在检查每个像素。但是如果边界像素和内部像素有单独的循环,则可以避免对 max 和 min 的大量调用。

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

关于matlab - 在opencv中寻找熵,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20371053/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com