天天看点

图像处理------简单综合实例(大米计数)

一位网友给我发了几张灰度图像,说是他们单位的工业相机拍摄的,画质非常的清楚,他们

单位是农业科研单位,特别想知道种子的数量,他想知道的是每次工业相机拍摄种子图片中

有多少颗粒种子,想到了用图像处理的办法解决他们的问题,看了他给我照片,以大米种子

为例。实现了一个简单的算法流程,可以得到种子的数目。

大致算法分为以下三个步骤:

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...