我正在尝试将以下代码从matlab转换为c ++
function data = process(data)
data = medfilt2(data, [7 7], 'symmetric');
mask = fspecial('gaussian', [35 35], 12);
data = imfilter(data, mask, 'replicate', 'same');
maximum = max(data(:));
data = 1 ./ ( data/maximum );
data(data > 10) = 16;
end
我在medfilt2中的问题 - 这是一个2D中值滤波器,我需要它支持每像素10位和更多图像。
1.我研究过openCV它有一个5x5中值滤波器,支持16位,但7x7只支持字节。
http://docs.opencv.org/2.4/modules/imgproc/doc/filtering.html?highlight=medianblur#medianblur
2.我也有,看看英特尔IPP,但我只能看到一维中值滤波器 https://software.intel.com/en-us/node/502283
2D滤镜是否有快速实施?
寻找类似的东西:
FAST MEDIAN FILTERING WITH IMPLEMENTATIONS IN C/C++/C#/VB.NET/Delphi中有更多代码示例。
答案 0 :(得分:6)
由于OpenCV没有为大内核大小(大于5)实现16位中值滤波器,我尝试了三种不同的策略。
所有这些都基于Huang的[2]滑动窗口算法。也就是说,当窗口从左向右滑动时,通过移除和插入像素条目来更新直方图。这对于8位图像来说非常简单,并且已经在OpenCV中实现。但是,大的65536 bin直方图使计算有点困难。
...算法仍然保持为O(log r),但存储注意事项使其对16位图像不实用,对浮点图像不可能。 [3]
我在适用的地方使用了algorithm
C ++标准库,并没有实现Weiss'其他优化策略。
1)一种天真的排序实现。我认为这是任意像素类型的最佳起点(特别是浮动)。
// copy pixels in the sliding window to a temporary vec and
// compute the median value (size is always odd)
memcpy( &v[0], &window[0], window.size() * sizeof(_Type) );
std::vector< _Type >::iterator it = v.begin() + v.size()/2;
std::nth_element( v.begin(), it, v.end() );
return *it;
2)稀疏直方图。我们不想跨越65536个箱来找到每个像素的中位数,那么如何存储稀疏直方图呢?同样,这适用于所有像素类型,但如果窗口中的所有像素都不同(例如浮点数),它就没有意义。
typedef std::map< _Type, int > Map;
//...
// inside the sliding window, update the histogram as follows
for ( /* pixels to remove */ )
{
// _Type px
Map::iterator it = map.find( px );
if ( it->second > 1 )
it->second -= 1;
else
map.erase( it );
}
// ...
for ( /* pixels to add */ )
{
// _Type px
Map::iterator lower = map.lower_bound( px );
if ( lower != map.end() && lower->first == px )
lower->second += 1;
else
map.insert( lower, std::pair<_Type,int>( px, 1 ) );
}
//... and compute the median by integrating from the one end until
// until the appropriate sum is reached ..
3)密集的直方图。所以这是密集的直方图,但是我们不是简单的65536数组,而是通过将搜索划分为子区域来使搜索更容易,例如:
[0...65535] <- px
[0...4095] <- px / 16
[0...255] <- px / 256
[0...15] <- px / 4096
这使插入速度变慢(按常数时间),但搜索速度要快得多。我找到了16个很好的数字。
图我测试了方法(1)红色,(2)蓝色和(3)黑色相互对比和8bpp OpenCV(绿色)。除OpenCV外,输入图像均为16-bpp灰度。虚线在动态范围[0,255]处被截断,平滑线在[0,8020]被截断(通过乘以16并平滑以在像素值上添加更多方差)。
有趣的是随着像素值的方差增加,稀疏直方图的偏差。 Nth-element总是安全的,OpenCV是最快的(如果8bpp没问题),密集的直方图落后。
我使用的是Windows 7,8 x 3.4 GHz和Visual Studio v.10。我的运行是多线程的,OpenCV实现是单线程的。输入图像大小2136x3201(http://i.imgur.com/gg9Z2aB.jpg,来自Vogue)。
[2]:Huang,T:&#34;二维信号处理II:变换 和中位数滤波器&#34;,1981
[3]:Weiss,B:&#34; Fast median and Bilateral Filtering&#34;,2006
答案 1 :(得分:1)
我在网上找到了这个,它与OpenCV的算法相同,但扩展到16位并优化为SSE。
https://github.com/aoles/EBImage/blob/master/src/medianFilter.c