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 008package edu.wpi.first.wpilibj.image; 009 010import edu.wpi.first.wpilibj.util.SortedVector; 011import com.ni.vision.NIVision; 012 013/** 014 * An image where each pixel is treated as either on or off. 015 * 016 * @author dtjones 017 */ 018public class BinaryImage extends MonoImage { 019 private int numParticles = -1; 020 021 BinaryImage() throws NIVisionException { 022 } 023 024 BinaryImage(BinaryImage sourceImage) { 025 super(sourceImage); 026 } 027 028 /** 029 * Returns the number of particles. 030 * 031 * @return The number of particles 032 */ 033 public int getNumberParticles() throws NIVisionException { 034 if (numParticles < 0) 035 numParticles = NIVision.imaqCountParticles(image, 1); 036 return numParticles; 037 } 038 039 040 private class ParticleSizeReport { 041 final int index; 042 final double size; 043 044 public ParticleSizeReport(int index) throws NIVisionException { 045 if ((!(index < BinaryImage.this.getNumberParticles())) || index < 0) 046 throw new IndexOutOfBoundsException(); 047 this.index = index; 048 size = ParticleAnalysisReport.getParticleToImagePercent(BinaryImage.this, index); 049 } 050 051 public ParticleAnalysisReport getParticleAnalysisReport() throws NIVisionException { 052 return new ParticleAnalysisReport(BinaryImage.this, index); 053 } 054 } 055 056 /** 057 * Get a particle analysis report for the particle at the given index. 058 * 059 * @param index The index of the particle to report on. 060 * @return The ParticleAnalysisReport for the particle at the given index 061 */ 062 public ParticleAnalysisReport getParticleAnalysisReport(int index) throws NIVisionException { 063 if (!(index < getNumberParticles())) throw new IndexOutOfBoundsException(); 064 return new ParticleAnalysisReport(this, index); 065 } 066 067 /** 068 * Gets all the particle analysis reports ordered from largest area to smallest. 069 * 070 * @param size The number of particles to return 071 * @return An array of ParticleReports from largest area to smallest 072 */ 073 public ParticleAnalysisReport[] getOrderedParticleAnalysisReports(int size) throws NIVisionException { 074 if (size > getNumberParticles()) 075 size = getNumberParticles(); 076 ParticleSizeReport[] reports = new ParticleSizeReport[size]; 077 SortedVector sorter = new SortedVector(new SortedVector.Comparator() { 078 public int compare(Object object1, Object object2) { 079 ParticleSizeReport p1 = (ParticleSizeReport) object1; 080 ParticleSizeReport p2 = (ParticleSizeReport) object2; 081 if (p1.size < p2.size) 082 return -1; 083 else if (p1.size > p2.size) 084 return 1; 085 return 0; 086 } 087 }); 088 for (int i = 0; i < getNumberParticles(); i++) 089 sorter.addElement(new ParticleSizeReport(i)); 090 sorter.setSize(size); 091 sorter.copyInto(reports); 092 ParticleAnalysisReport[] finalReports = new ParticleAnalysisReport[reports.length]; 093 for (int i = 0; i < finalReports.length; i++) 094 finalReports[i] = reports[i].getParticleAnalysisReport(); 095 return finalReports; 096 } 097 098 /** 099 * Gets all the particle analysis reports ordered from largest area to smallest. 100 * 101 * @return An array of ParticleReports from largest are to smallest 102 */ 103 public ParticleAnalysisReport[] getOrderedParticleAnalysisReports() throws NIVisionException { 104 return getOrderedParticleAnalysisReports(getNumberParticles()); 105 } 106 107 108 public void write(String fileName) throws NIVisionException { 109 NIVision.RGBValue colorTable = new NIVision.RGBValue(0, 0, 255, 0); 110 try { 111 NIVision.imaqWriteFile(image, fileName, colorTable); 112 } finally { 113 colorTable.free(); 114 } 115 } 116 117 /** 118 * removeSmallObjects filters particles based on their size. 119 * The algorithm erodes the image a specified number of times and keeps the 120 * particles from the original image that remain in the eroded image. 121 * 122 * @param connectivity8 true to use connectivity-8 or false for connectivity-4 to determine 123 * whether particles are touching. For more information about connectivity, see Chapter 9, 124 * Binary Morphology, in the NI Vision Concepts manual. 125 * @param erosions the number of erosions to perform 126 * @return a BinaryImage after applying the filter 127 * @throws NIVisionException 128 */ 129 public BinaryImage removeSmallObjects(boolean connectivity8, int erosions) throws NIVisionException { 130 BinaryImage result = new BinaryImage(); 131 NIVision.imaqSizeFilter(result.image, image, connectivity8 ? 1 : 0, erosions, NIVision.SizeType.KEEP_LARGE, null); 132 result.free(); 133 return result; 134 } 135 136 /** 137 * removeLargeObjects filters particles based on their size. 138 * The algorithm erodes the image a specified number of times and discards the 139 * particles from the original image that remain in the eroded image. 140 * 141 * @param connectivity8 true to use connectivity-8 or false for connectivity-4 to determine 142 * whether particles are touching. For more information about connectivity, see Chapter 9, 143 * Binary Morphology, in the NI Vision Concepts manual. 144 * @param erosions the number of erosions to perform 145 * @return a BinaryImage after applying the filter 146 * @throws NIVisionException 147 */ 148 public BinaryImage removeLargeObjects(boolean connectivity8, int erosions) throws NIVisionException { 149 BinaryImage result = new BinaryImage(); 150 NIVision.imaqSizeFilter(result.image, image, connectivity8 ? 1 : 0, erosions, NIVision.SizeType.KEEP_SMALL, null); 151 return result; 152 } 153 154 public BinaryImage convexHull(boolean connectivity8) throws NIVisionException { 155 BinaryImage result = new BinaryImage(); 156 NIVision.imaqConvexHull(result.image, image, connectivity8 ? 1 : 0); 157 return result; 158 } 159 160 public BinaryImage particleFilter(NIVision.ParticleFilterCriteria2[] criteria) throws NIVisionException { 161 BinaryImage result = new BinaryImage(); 162 NIVision.ParticleFilterOptions2 options = new NIVision.ParticleFilterOptions2(0, 0, 0, 1); 163 NIVision.imaqParticleFilter4(result.image, image, criteria, options, null); 164 options.free(); 165 return result; 166 } 167}