生活随笔
收集整理的這篇文章主要介紹了
图像处理之应用篇-大米计数续
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
from: http://blog.csdn.net/jia20003/article/details/7757276
圖像處理之應用篇-大米計數續
背景介紹:
請看博客文章《圖像處理之簡單綜合實例(大米計數)》
其實拍出來的照片更多的是含有大米顆粒相互接觸,甚至于有點重疊的照片
要準確計算大米的顆粒數非常困難,通過圖像形態學開閉操作,腐蝕等手
段嘗試以后效果不是很好。最終發現一種簡單明了但是有微小誤差的計數
方法。照相機圖片:
算法思想:
主要是利用連通區域發現算法,發現所有連通區域,使用二分法,截取較小
部分的連通區域集合,求取平均連通區域面積,根據此平均連通區域面積,
作為單個大米大小,從而求取出粘連部分的大米顆粒數,完成對整個大米
數目的統計:
缺點:
平均連通區域面積的計算受制于兩個因素,一個是最小連通區域集合的選取算法,
二個樣本數量。算法結果跟實際結果有一定的誤差,但是誤差在1%左右。
?
程序算法代碼詳解
將輸入圖像轉換為黑白二值圖像,求得連通區域的算法代碼如下:
src = super.filter(src,null);
getRGB(src, 0, 0, width,height, inPixels );
FastConnectedComponentLabelAlgfccAlg = new FastConnectedComponentLabelAlg();
fccAlg.setBgColor(0);
int[] outData = fccAlg.doLabel(inPixels, width, height);
?
獲取平均大米顆粒連通區域的代碼如下:
Integer[] values =labelMap.values().toArray(new Integer[0]);
Arrays.sort(values);
int minRiceNum = values.length/4;
float sum = 0;
for(int v=offset; v<minRiceNum +offset; v++) {
sum += values[v].intValue();
}
float minMeans = sum / (float)minRiceNum;
System.out.println(" minMeans = " + minMeans);
?
程序時序圖如下:
程序運行效果如下:
實際大米顆粒數目為202,正確率為99%
完成大米數目統計的源代碼如下(其它相關代碼見以前的圖像處理系列文章):
[java] view plaincopy
public?class?FindRiceFilter?extends?BinaryFilter?{????????????private?int?sumRice;??????private?int?offset?=?10;????????????public?int?getSumRice()?{??????????return?this.sumRice;??????}????????????public?void?setOffset(int?pos)?{??????????this.offset?=?pos;??????}????????@Override??????public?BufferedImage?filter(BufferedImage?src,?BufferedImage?dest)?{??????????int?width?=?src.getWidth();??????????int?height?=?src.getHeight();??????????if?(?dest?==?null?)??????????????dest?=?createCompatibleDestImage(?src,?null?);????????????int[]?inPixels?=?new?int[width*height];??????????int[]?outPixels?=?new?int[width*height];??????????src?=?super.filter(src,?null);??????????getRGB(src,?0,?0,?width,?height,?inPixels?);??????????FastConnectedComponentLabelAlg?fccAlg?=?new?FastConnectedComponentLabelAlg();??????????fccAlg.setBgColor(0);??????????int[]?outData?=?fccAlg.doLabel(inPixels,?width,?height);??????????????????????????????HashMap<Integer,?Integer>?labelMap?=?new?HashMap<Integer,?Integer>();??????????for(int?d=0;?d<outData.length;?d++)?{??????????????if(outData[d]?!=?0)?{??????????????????if(labelMap.containsKey(outData[d]))?{??????????????????????Integer?count?=?labelMap.get(outData[d]);??????????????????????count+=1;??????????????????????labelMap.put(outData[d],?count);??????????????????}?else?{??????????????????????labelMap.put(outData[d],?1);??????????????????}??????????????}??????????}????????????????????Integer[]?values?=?labelMap.values().toArray(new?Integer[0]);??????????Arrays.sort(values);??????????int?minRiceNum?=?values.length/4;??????????float?sum?=?0;??????????for(int?v=?offset;?v<minRiceNum?+?offset;?v++)?{??????????????sum?+=?values[v].intValue();??????????}??????????float?minMeans?=?sum?/?(float)minRiceNum;??????????System.out.println("?minMeans?=?"?+?minMeans);??????????????????????????????Integer[]?keys?=?labelMap.keySet().toArray(new?Integer[0]);??????????Arrays.sort(keys);??????????int?threshold?=?10;??????????ArrayList<Integer>?listKeys?=?new?ArrayList<Integer>();??????????for(Integer?key?:?keys)?{??????????????if(labelMap.get(key)?<=threshold){??????????????????listKeys.add(key);??????????????}?else?{??????????????????float?xx?=?labelMap.get(key);??????????????????float?intPart?=?(float)Math.floor(xx?/?minMeans?+?0.5f);??????????????????sumRice?+=?intPart;??????????????}??????????}??????????System.out.println(?"Number?of?rice??=?"?+?sumRice);????????????????????????????????????????int?index?=?0;??????????????for(int?row=0;?row<height;?row++)?{????????????????int?ta?=?0,?tr?=?0,?tg?=?0,?tb?=?0;????????????????for(int?col=0;?col<width;?col++)?{????????????????????index?=?row?*?width?+?col;????????????????????ta?=?(inPixels[index]?>>?24)?&?0xff;????????????????????tr?=?(inPixels[index]?>>?16)?&?0xff;????????????????????tg?=?(inPixels[index]?>>?8)?&?0xff;????????????????????tb?=?inPixels[index]?&?0xff;??????????????????if(outData[index]?!=?0?&&?validRice(outData[index],?listKeys))?{??????????????????????tr?=?tg?=?tb?=?255;??????????????????}?else?{??????????????????????tr?=?tg?=?tb?=?0;??????????????????}??????????????????outPixels[index]?=?(ta?<<?24)?|?(tr?<<?16)?|?(tg?<<?8)?|?tb;??????????????}??????????}??????????setRGB(?dest,?0,?0,?width,?height,?outPixels?);??????????return?dest;??????}????????private?boolean?validRice(int?i,?ArrayList<Integer>?listKeys)?{??????????for(Integer?key?:?listKeys)?{??????????????if(key?==?i)?{??????????????????return?false;??????????????}??????????}??????????return?true;??????}????}??
轉載文章請務必注明出處
總結
以上是生活随笔為你收集整理的图像处理之应用篇-大米计数续的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。