天天看點

圖像處理------簡單綜合執行個體(大米計數)

一位網友給我發了幾張灰階圖像,說是他們機關的工業相機拍攝的,畫質非常的清楚,他們

機關是農業科研機關,特别想知道種子的數量,他想知道的是每次工業相機拍攝種子圖檔中

有多少顆粒種子,想到了用圖像處理的辦法解決他們的問題,看了他給我照片,以大米種子

為例。實作了一個簡單的算法流程,可以得到種子的數目。

大緻算法分為以下三個步驟:

1.      将灰階圖像二值化,二值化方法可以參考以前的文章,求取像素平均值,灰階直方圖都

          可以

2.      去掉二值化以後的圖像中幹擾噪聲。

3.      得到種子數目,用彩色标記出來。

圖像處理------簡單綜合執行個體(大米計數)

源圖像如下:

圖像處理------簡單綜合執行個體(大米計數)

程式進行中間結果及最終效果如下:

圖像處理------簡單綜合執行個體(大米計數)

大米計數與噪聲塊消去算法基于連通元件标記算法,源代碼如下:

package com.gloomyfish.rice.analysis;  

import java.awt.image.bufferedimage;  

import java.util.arraylist;  

import java.util.arrays;  

import java.util.hashmap;  

import com.gloomyfish.face.detection.abstractbufferedimageop;  

import com.gloomyfish.face.detection.fastconnectedcomponentlabelalg;  

public class findricefilter extends abstractbufferedimageop {  

    private int sumrice;  

    public int getsumrice() {  

        return this.sumrice;  

    }  

    @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];  

        getrgb(src, 0, 0, width, height, inpixels );  

        fastconnectedcomponentlabelalg fccalg = new fastconnectedcomponentlabelalg();  

        fccalg.setbgcolor(0);  

        int[] outdata = fccalg.dolabel(inpixels, width, height);  

        // labels statistic  

        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);  

                }  

            }  

        }  

        // try to find the max connected component  

        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);  

            system.out.println( "number of " + key + " = " + labelmap.get(key));  

        sumrice = keys.length - listkeys.size();  

        // calculate means of pixel    

        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;  

                    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;  

}  

大米着色處理很簡單,隻是簡單rgb固定着色,源碼如下:

public class colorfulricefilter extends abstractbufferedimageop {  

        int index = 0, srcrgb;  

            int ta = 255, tr = 0, tg = 0, tb = 0;    

            for(int col=0; col<width; col++) {   

//                ta = (inpixels[index] >> 24) & 0xff;    

//                tr = (inpixels[index] >> 16) & 0xff;    

//                tg = (inpixels[index] >> 8) & 0xff;    

//                tb = inpixels[index] & 0xff;    

                srcrgb = inpixels[index] & 0x000000ff;  

                if(srcrgb > 0 && row < 140) {  

                    tr = 0;  

                    tg = 255;  

                    tb = 0;  

                } else if(srcrgb > 0 && row >= 140 && row <=280) {  

                    tg = 0;  

                    tb = 255;  

                } else if(srcrgb > 0 && row >=280) {  

                    tr = 255;  

                else {  

測試程式ui代碼如下:

import java.awt.borderlayout;  

import java.awt.color;  

import java.awt.dimension;  

import java.awt.flowlayout;  

import java.awt.graphics;  

import java.awt.graphics2d;  

import java.awt.image;  

import java.awt.mediatracker;  

import java.awt.event.actionevent;  

import java.awt.event.actionlistener;  

import java.io.file;  

import java.io.ioexception;  

import javax.imageio.imageio;  

import javax.swing.jbutton;  

import javax.swing.jcomponent;  

import javax.swing.jfilechooser;  

import javax.swing.jframe;  

import javax.swing.jpanel;  

public class mainframe extends jcomponent implements actionlistener {  

    /** 

     *  

     */  

    private static final long serialversionuid = 1518574788794973574l;  

    public final static string browse_cmd = "browse...";  

    public final static string noise_cmd = "remove noise";  

    public final static string fun_cmd = "colorful rice";  

    private bufferedimage rawimg;  

    private bufferedimage resultimage;  

    private mediatracker tracker;  

    private dimension mysize;  

    // jbuttons  

    private jbutton browsebtn;  

    private jbutton noisebtn;  

    private jbutton colorfulbtn;  

    // rice number....  

    private int ricenum = -1;  

    public mainframe() {  

        jpanel btnpanel = new jpanel();  

        btnpanel.setlayout(new flowlayout(flowlayout.left));  

        browsebtn = new jbutton("browse...");  

        noisebtn = new jbutton("remove noise");  

        colorfulbtn = new jbutton("colorful rice");  

        browsebtn.settooltiptext("please select image file...");  

        noisebtn.settooltiptext("find connected region and draw red rectangle");  

        colorfulbtn.settooltiptext("remove the minor noise region pixels...");  

        // buttons  

        btnpanel.add(browsebtn);  

        btnpanel.add(noisebtn);  

        btnpanel.add(colorfulbtn);  

        // setup listener...  

        browsebtn.addactionlistener(this);  

        noisebtn.addactionlistener(this);  

        colorfulbtn.addactionlistener(this);  

        browsebtn.setenabled(true);  

        noisebtn.setenabled(true);  

        colorfulbtn.setenabled(true);  

//      minx = miny =  10000;  

//      maxx = maxy = -1;  

        mysize = new dimension(500, 300);  

        jframe demoui = new jframe("rice detection demo");  

        demoui.getcontentpane().setlayout(new borderlayout());  

        demoui.getcontentpane().add(this, borderlayout.center);  

        demoui.getcontentpane().add(btnpanel, borderlayout.south);  

        demoui.setdefaultcloseoperation(jframe.exit_on_close);  

        demoui.pack();  

        demoui.setvisible(true);  

    public void paint(graphics g) {  

        graphics2d g2 = (graphics2d) g;  

        if(rawimg != null) {  

            image scaledimage = rawimg.getscaledinstance(200, 200, image.scale_fast);  

            g2.drawimage(scaledimage, 0, 0, 200, 200, null);  

        if(resultimage != null) {  

            image scaledimage = resultimage.getscaledinstance(200, 200, image.scale_fast);  

            g2.drawimage(scaledimage, 210, 0, 200, 200, null);  

        g2.setpaint(color.red);  

        if(ricenum > 0) {  

            g2.drawstring("number of rice : " + ricenum, 100, 300);  

        } else {  

            g2.drawstring("number of rice : unknown", 100, 300);  

    public dimension getpreferredsize() {  

        return mysize;  

    public dimension getminimumsize() {  

    public dimension getmaximumsize() {  

    public static void main(string[] args) {  

        new mainframe();  

    public void actionperformed(actionevent e) {  

        if(browse_cmd.equals(e.getactioncommand())) {  

            jfilechooser chooser = new jfilechooser();  

            chooser.showopendialog(null);  

            file f = chooser.getselectedfile();  

            bufferedimage bimage = null;  

            if(f == null) return;  

            try {  

                bimage = imageio.read(f);  

            } catch (ioexception e1) {  

                e1.printstacktrace();  

            tracker = new mediatracker(this);  

            tracker.addimage(bimage, 1);  

            // blocked 10 seconds to load the image data  

                if (!tracker.waitforid(1, 10000)) {  

                    system.out.println("load error.");  

                    system.exit(1);  

                }// end if  

            } catch (interruptedexception ine) {  

                ine.printstacktrace();  

                system.exit(1);  

            } // end catch  

            binaryfilter bfilter = new binaryfilter();  

            rawimg = bfilter.filter(bimage, null);  

            repaint();  

        } else if(noise_cmd.equals(e.getactioncommand())) {  

            findricefilter frfilter = new findricefilter();  

            resultimage = frfilter.filter(rawimg, null);  

            ricenum = frfilter.getsumrice();  

        } else if(fun_cmd.equals(e.getactioncommand())) {  

            colorfulricefilter cfilter = new colorfulricefilter();  

            resultimage = cfilter.filter(resultimage, null);  

            // do nothing...