在中值濾波器和均值濾波器之後, 我們看到是中值濾波器的改版, 這個名字我實在不好把握 Hybrid Median Filter實在不知道翻譯成什麼比較妥當.只好沿用了混合動力車裡面的混合二字, 姑且把這種濾波器命名為混合中值濾波器. 這個濾波器的工作流程較之原先有些繁瑣, 來看看這張圖
圖截的有些模糊, 但是還是看出了大致的流程, 首先當前像素的上下左右和自身取中值
, 然後左上右上左下右下和自身取中值
, 完了前面的兩個值和當前像素值再取一次中值
, 得到的值就是最後的終極像素值了. 可以看到這個流程還是有些複雜的.. 那他的效果如何捏? 我們還是和前幾次一樣來觀察一把:
原圖 HMF之後:
雜訊汙染: HMF之後:
從前面的圖片可以看到, 圖片從高銳度經由混合中值濾波之後, 銳度下降了. 但是在去雜訊的環節上, 這個所謂的混合中值濾波器表現的甚至不如中值濾波來的效果好, 當然因為這裡的雜訊是隨機的, 可能有些因素在其中. 但從原理上分析.這種濾波器確實存在不能過濾掉的可能, 原因在什麼地方呢? 且看我們這個大圖中的一個小局部:
把圖放大之後看的很清楚了, 在紅色的圓圈圈出來的地方, 不出意外的發現了水平連續的3個白色像素. 再聯想到我們之前經過HMF之後的就不難得出結論, 就是者連續的3個點造成了最後的這個白色像素. 怎麼說呢? 很簡單, 在HMF的第一步過程中, 因為我們選擇的點是5各點, 上下左右中, 那麼經過計算, 就是白色無疑了, 不管第二步得到什麼像素, 在第三步的時候, 讓2個白色取中值, 肯定得到的白色像素了! 仔細想來確實是這個麼道理. 但是median filter的時候因為要整體考慮9個像素的中值, 這裡很有可能就不是白色了! 所以這個混合中值濾波器會在保持線條的邊緣上有獨到之處(因為比較容易保持聯絡像素的顏色不受傷害), 而消除雜訊還是median filter表現更勝一籌.
老規矩, 最後再貼一下處理的函數代碼:
unsigned char median(unsigned char* elements, int width)<br />{<br />// Order elements (only half of them)<br />for (int i = 0; i < (width >> 1) + 1; ++i)<br />{<br />// Find position of minimum element<br />int min = i;<br />for (int j = i + 1; j < width; ++j)<br />if (elements[j] < elements[min])<br />min = j;<br />// Put found minimum element in its place<br />unsigned char temp = elements[i];<br />elements[i] = elements[min];<br />elements[min] = temp;<br />}<br />// Get result - the middle element<br />return elements[width >> 1];<br />}<br />/**<br />** method to remove noise from the corrupted image by hybrid median value<br />* @param corrupted input grayscale binary array with corrupted info<br />* @param smooth output data for smooth result, the memory need to be allocated outside of the function<br />* @param width width of the input grayscale image<br />* @param height height of the input grayscale image<br />*/<br />void hybridMedianFilter (unsigned char* corrupted, unsigned char* smooth, int width, int height)<br />{<br />memcpy ( smooth, corrupted, width*height*sizeof(unsigned char) );<br />for (int j=1;j<height-1;j++)<br />{<br />for (int i=1;i<width-1;i++)<br />{<br />unsigned char window[5];<br />unsigned char results[3];<br />// Pick up cross-window elements<br />window[0] = corrupted[(j - 1) * width + i];<br />window[1] = corrupted[j * width + i - 1];<br />window[2] = corrupted[j * width + i];<br />window[3] = corrupted[j * width + i + 1];<br />window[4] = corrupted[(j + 1) * width + i];<br />// Get median<br />results[0] = median(window, 5);<br />// Pick up x-window elements<br />window[0] = corrupted[(j - 1) * width + i - 1];<br />window[1] = corrupted[(j - 1) * width + i + 1];<br />window[2] = corrupted[j * width + i];<br />window[3] = corrupted[(j + 1) * width + i - 1];<br />window[4] = corrupted[(j + 1) * width + i + 1];<br />// Get median<br />results[1] = median(window, 5);<br />// Pick up leading element<br />results[2] = corrupted[j * width + i];<br />// Get result<br />smooth[j*width+i] = median(results, 3);<br />}<br />}<br />}<br />
因為要取中值, 還附加了一個取中值的函數median:)