我正在尝试将以下代码从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.我也有研究intel IPP,但我只能看到一维中值滤波器
https://software.intel.com/en-us/node/502283
二维过滤器有快速实现吗?
寻找类似的东西:
黄兆。编辑施普林格出版社。 1981年。
FAST MEDIAN FILTERING WITH IMPLEMENTATIONS IN C/C++/C#/VB.NET/Delphi中有更多代码示例。
我还找到了Median Filtering in Constant Time。
最佳答案
出于OpenCV对于大型内核(大于5)不执行16位中值过滤器这一事实,我尝试了三种不同的策略。
它们都基于Huang的[2]滑动窗口算法。即,通过在窗口从左向右滑动时删除并插入像素条目来更新直方图。对于8位图像,这非常简单,并且已经在OpenCV中实现。但是,较大的65536 bin直方图会使计算有些困难。
我在适用的情况下使用了algorithm
C++标准库,但未实现Weiss的其他优化策略。
1)天真的排序实现。我认为这是任意像素类型(尤其是 float 像素)的最佳起点。
// 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个bin来找到每个像素的中值,那么如何存储稀疏直方图呢?同样,这适用于所有像素类型,但如果窗口中的所有像素都不同(例如, float ),则没有任何意义。
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)密集的直方图。因此,这是密集的直方图,但是我们将其划分为子bin,例如,代替了一个简单的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并进行平滑处理以在像素值上添加更多的方差)。
有趣的是,随着像素值方差的增加,稀疏直方图的发散。 N元素始终是安全的赌注,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:“二维信号处理II:变换
和中值过滤器”,1981年
[3]:Weiss,B:“快速中值和双边过滤”,2006年