001    /*----------------------------------------------------------------------------*/
002    /* Copyright (c) FIRST 2008-2012. All Rights Reserved.                        */
003    /* Open Source Software - may be modified and shared by FRC teams. The code   */
004    /* must be accompanied by the FIRST BSD license file in the root directory of */
005    /* the project.                                                               */
006    /*----------------------------------------------------------------------------*/
007    
008    package edu.wpi.first.wpilibj.image;
009    
010    import com.sun.cldc.jna.Pointer;
011    import edu.wpi.first.wpilibj.util.SortedVector;
012    
013    /**
014     * An image where each pixel is treated as either on or off.
015     * @author dtjones
016     */
017    public class BinaryImage extends MonoImage {
018        private int numParticles = -1;
019    
020        BinaryImage() throws NIVisionException{
021        }
022    
023        BinaryImage(BinaryImage sourceImage) {
024            super(sourceImage);
025        }
026    
027        /**
028         * Returns the number of particles.
029         * @return The number of particles
030         */
031        public int getNumberParticles () throws NIVisionException{
032            if (numParticles < 0)
033                numParticles = NIVision.countParticles(image);
034            return numParticles;
035        }
036    
037    
038        private class ParticleSizeReport{
039            final int index;
040            final double size;
041            public ParticleSizeReport(int index) throws NIVisionException{
042                if ((!(index < BinaryImage.this.getNumberParticles())) || index < 0)
043                    throw new IndexOutOfBoundsException();
044                this.index = index;
045                size = ParticleAnalysisReport.getParticleToImagePercent(BinaryImage.this, index);
046            }
047            public ParticleAnalysisReport getParticleAnalysisReport () throws NIVisionException{
048                return new ParticleAnalysisReport(BinaryImage.this, index);
049            }
050        }
051    
052        /**
053         * Get a particle analysis report for the particle at the given index.
054         * @param index The index of the particle to report on.
055         * @return The ParticleAnalysisReport for the particle at the given index
056         */
057        public ParticleAnalysisReport getParticleAnalysisReport(int index) throws NIVisionException{
058            if (!(index < getNumberParticles())) throw new IndexOutOfBoundsException();
059            return new ParticleAnalysisReport(this, index);
060        }
061    
062        /**
063         * Gets all the particle analysis reports ordered from largest area to smallest.
064         * @param size The number of particles to return
065         * @return An array of ParticleReports from largest area to smallest
066         */
067        public ParticleAnalysisReport[] getOrderedParticleAnalysisReports(int size) throws NIVisionException{
068            if (size > getNumberParticles())
069                size = getNumberParticles();
070            ParticleSizeReport[] reports = new ParticleSizeReport[size];
071            SortedVector sorter = new SortedVector(new SortedVector.Comparator() {
072                public int compare(Object object1, Object object2) {
073                    ParticleSizeReport p1 = (ParticleSizeReport)object1;
074                    ParticleSizeReport p2 = (ParticleSizeReport)object2;
075                    if (p1.size < p2.size)
076                        return -1;
077                    else if (p1.size > p2.size)
078                        return 1;
079                    return 0;
080                }
081            });
082            for (int i = 0; i < getNumberParticles(); i++)
083                sorter.addElement(new ParticleSizeReport(i));
084            sorter.setSize(size);
085            sorter.copyInto(reports);
086            ParticleAnalysisReport[] finalReports = new ParticleAnalysisReport[reports.length];
087            for (int i = 0; i < finalReports.length; i++)
088                finalReports[i] = reports[i].getParticleAnalysisReport();
089            return finalReports;
090        }
091    
092        /**
093         * Gets all the particle analysis reports ordered from largest area to smallest.
094         * @return An array of ParticleReports from largest are to smallest
095         */
096        public ParticleAnalysisReport[] getOrderedParticleAnalysisReports() throws NIVisionException{
097            return getOrderedParticleAnalysisReports(getNumberParticles());
098        }
099    
100    
101        public void write(String fileName) throws NIVisionException{
102            Pointer colorTable = new Pointer(1024);
103            //Black Background
104            colorTable.setByte(0, (byte)0);   //B
105            colorTable.setByte(1, (byte)0);   //G
106            colorTable.setByte(2, (byte)0);   //R
107            colorTable.setByte(3, (byte)0);     //Alpha
108            //Red Particles:
109            colorTable.setByte(4, (byte)0);     //B
110            colorTable.setByte(5, (byte)0);     //G
111            colorTable.setByte(6, (byte)255);   //R
112            colorTable.setByte(7, (byte)0);     //Alpha
113            try {
114                NIVision.writeFile(image, fileName, colorTable);
115            } finally {
116                colorTable.free();
117            }
118        }
119        
120        /**
121         * removeSmallObjects filters particles based on their size.
122         * The algorithm erodes the image a specified number of times and keeps the
123         * particles from the original image that remain in the eroded image.
124         * @param connectivity8 true to use connectivity-8 or false for connectivity-4 to determine
125         * whether particles are touching. For more information about connectivity, see Chapter 9,
126         * Binary Morphology, in the NI Vision Concepts manual.
127         * @param erosions the number of erosions to perform
128         * @return a BinaryImage after applying the filter
129         * @throws NIVisionException 
130         */
131        public BinaryImage removeSmallObjects(boolean connectivity8, int erosions) throws NIVisionException {
132            BinaryImage result = new BinaryImage();
133            try {
134                NIVision.sizeFilter(result.image, image, connectivity8, erosions, true);
135            } catch (NIVisionException ex) {
136                result.free();
137                throw ex;
138            }
139            return result;
140        }
141        
142       /**
143         * removeLargeObjects filters particles based on their size.
144         * The algorithm erodes the image a specified number of times and discards the
145         * particles from the original image that remain in the eroded image.
146         * @param connectivity8 true to use connectivity-8 or false for connectivity-4 to determine
147         * whether particles are touching. For more information about connectivity, see Chapter 9,
148         * Binary Morphology, in the NI Vision Concepts manual.
149         * @param erosions the number of erosions to perform
150         * @return a BinaryImage after applying the filter
151         * @throws NIVisionException 
152         */
153        public BinaryImage removeLargeObjects(boolean connectivity8, int erosions) throws NIVisionException {
154            BinaryImage result = new BinaryImage();
155            try {
156                NIVision.sizeFilter(result.image, image, connectivity8, erosions, false);
157            } catch (NIVisionException ex) {
158                result.free();
159                throw ex;
160            }
161            return result;
162        }
163        
164        public BinaryImage convexHull(boolean connectivity8) throws NIVisionException {
165            BinaryImage result = new BinaryImage();
166            try {
167                NIVision.convexHull(result.image, image, connectivity8 ? 1 : 0);
168            } catch (NIVisionException ex) {
169                result.free();
170                throw ex;
171            }
172            return result;
173        }
174        
175        public BinaryImage particleFilter(CriteriaCollection criteria) throws NIVisionException {
176            BinaryImage result = new BinaryImage();
177            NIVision.particleFilter(result.image, image, criteria);
178            return result;
179        }
180    }