-
-
Save keionbis/c3cdee36e2b6f8b2104d7d424039e10f to your computer and use it in GitHub Desktop.
Color detection example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.awt.image.BufferedImage; | |
import java.util.ArrayList; | |
import java.util.List; | |
import org.opencv.core.Core; | |
import org.opencv.core.CvType; | |
import org.opencv.core.Mat; | |
import org.opencv.core.MatOfByte; | |
import org.opencv.core.Point; | |
import org.opencv.core.Rect; | |
import org.opencv.core.Scalar; | |
import org.opencv.core.Size; | |
//import org.opencv.features2d.KeyPoint; | |
import org.opencv.imgproc.Imgproc; | |
import com.neuronrobotics.imageprovider.*; | |
//http://cell0907.blogspot.com/2013/07/tracking-ball-with-javaopencv.html | |
class MyColorDetector implements IObjectDetector{ | |
private Mat hsv_image = new Mat(); | |
private Mat thresholded = new Mat(); | |
private Mat thresholded2 = new Mat(); | |
private Mat circles = new Mat(); // No need (and don't know how) to initialize it. | |
// The function later will do it... (to a 1*N*CV_32FC3) | |
// Scalar hsv_min = new Scalar(200, 200, 200, 0); | |
// Scalar hsv_max = new Scalar(255, 255, 255, 0); | |
// Scalar hsv_min2 = new Scalar(50, 50, 50, 0); | |
// Scalar hsv_max2 = new Scalar(255, 255, 255, 0); | |
private double[] data = new double[3]; | |
private List<Mat> lhsv; | |
private Mat array255 ; | |
private Mat distance; | |
private Scalar hsv_min; | |
private Scalar hsv_max; | |
private Scalar hsv_min2; | |
private Scalar hsv_max2; | |
public MyColorDetector(Mat matImage,Scalar hsv_min, Scalar hsv_max,Scalar hsv_min2 ,Scalar hsv_max2) { | |
this.hsv_min = hsv_min; | |
this.hsv_max = hsv_max; | |
this.hsv_min2 = hsv_min2; | |
this.hsv_max2 = hsv_max2; | |
lhsv = new ArrayList<Mat>(3); | |
array255 = new Mat(matImage.height(), matImage.width(), | |
CvType.CV_8UC1); | |
array255.setTo(new Scalar(255)); | |
distance = new Mat(matImage.height(), matImage.width(), | |
CvType.CV_8UC1); | |
} | |
public void setThreshhold(Scalar hsv_min, Scalar hsv_max){ | |
this.hsv_min = hsv_min; | |
this.hsv_max = hsv_max; | |
} | |
public void setThreshhold2(Scalar hsv_min2 ,Scalar hsv_max2){ | |
this.hsv_min2 = hsv_min2; | |
this.hsv_max2 = hsv_max2; | |
} | |
public List<Detection> getObjects(BufferedImage incoming, BufferedImage disp){ | |
Mat inputImage = new Mat(); | |
OpenCVImageConversionFactory.bufferedImageToMat(incoming,inputImage); | |
Mat displayImage = new Mat(); | |
// One way to select a range of colors by Hue | |
Imgproc.cvtColor(inputImage, hsv_image, Imgproc.COLOR_BGR2HSV); | |
Core.inRange(hsv_image, hsv_min, hsv_max, thresholded); | |
Core.inRange(hsv_image, hsv_min2, hsv_max2, thresholded2); | |
Core.bitwise_or(thresholded, thresholded2, thresholded); | |
// Notice that the thresholds don't really work as a "distance" | |
// Ideally we would like to cut the image by hue and then pick just | |
// the area where S combined V are largest. | |
// Strictly speaking, this would be something like | |
// sqrt((255-S)^2+(255-V)^2)>Range | |
// But if we want to be "faster" we can do just (255-S)+(255-V)>Range | |
// Or otherwise 510-S-V>Range | |
// Anyhow, we do the following... Will see how fast it goes... | |
Core.split(hsv_image, lhsv); // We get 3 2D one channel Mats | |
Mat S = lhsv.get(1); | |
Mat V = lhsv.get(2); | |
Core.subtract(array255, S, S); | |
Core.subtract(array255, V, V); | |
S.convertTo(S, CvType.CV_32F); | |
V.convertTo(V, CvType.CV_32F); | |
Core.magnitude(S, V, distance); | |
Core.inRange(distance, new Scalar(0.0), new Scalar(200.0), thresholded2); | |
Core.bitwise_and(thresholded, thresholded2, thresholded); | |
// Apply the Hough Transform to find the circles | |
Imgproc.GaussianBlur(thresholded, thresholded, new Size(9, 9), 0, 0); | |
Imgproc.HoughCircles(thresholded, circles, Imgproc.CV_HOUGH_GRADIENT, | |
2, thresholded.height() / 4, 500, 50, 0, 0); | |
//Make the display image the thresholded image | |
thresholded.copyTo(displayImage); | |
// Imgproc.Canny(thresholded, thresholded, 500, 250); | |
// -- 4. Add some info to the image | |
data = inputImage.get(210, 210); | |
// int cols = circles.cols(); | |
int rows = circles.rows(); | |
int elemSize = (int) circles.elemSize(); // Returns 12 (3 * 4bytes in a | |
// float) | |
float[] data2 = new float[rows * elemSize / 4]; | |
ArrayList<Detection> myArray = new ArrayList<Detection>(); | |
Point center=null;// | |
if (data2.length > 0) { | |
circles.get(0, 0, data2); // Points to the first element and reads | |
// the whole thing | |
// into data2 | |
for (int i = 0; i < data2.length; i = i + 3) { | |
center = new Point(data2[i], data2[i + 1]); | |
Size objectSize= new Size((double) data2[i + 2], | |
(double) data2[i + 2]); | |
// Core.ellipse( this, center, new Size( rect.width*0.5, | |
// rect.height*0.5), 0, 0, 360, new Scalar( 255, 0, 255 ), 4, 8, | |
// 0 ); | |
Core.ellipse(displayImage, center,objectSize, 0, 0, 360, new Scalar(255, 0, | |
255), 4, 8, 0); | |
myArray.add(new Detection(center.x, center.y, objectSize.height)); | |
} | |
if(center != null){ | |
Core.putText( | |
displayImage, | |
String.format("Circles (" + String.valueOf(data[0]) + "," | |
+ String.valueOf(data[1]) + "," | |
+ String.valueOf(data[2]) + ")"), new Point(30, 30), 2 // FONT_HERSHEY_SCRIPT_SIMPLEX | |
, 0.5, new Scalar(100, 10, 10, 255), 3); | |
for(int i=0;i<myArray.size();i++){ | |
Point centerTmp = new Point(myArray.get(i).getX(), myArray.get(i).getY()); | |
Core.line(displayImage, new Point(150, 50), centerTmp, | |
new Scalar(100, 10, 10)/* CV_BGR(100,10,10) */, 3); | |
Core.circle(displayImage, centerTmp, 10, new Scalar(100, 10, 10), | |
3); | |
} | |
} | |
} | |
AbstractImageProvider.deepCopy(OpenCVImageConversionFactory.matToBufferedImage(displayImage),disp); | |
return myArray; | |
} | |
} | |
Scalar upper =new Scalar(30, 150, 0, 0); | |
Scalar lower =new Scalar(240, 166, 0, 0); | |
Scalar upper1 =new Scalar(360, 255, 255, 0); | |
Scalar lower1 =new Scalar(240, 0, 0, 0); | |
Mat inputImage = new Mat() | |
OpenCVImageConversionFactory.bufferedImageToMat(AbstractImageProvider.newBufferImage(640,480),inputImage); | |
return new CameraTab(camera0, new MyColorDetector(inputImage, | |
lower, | |
upper, | |
lower1, | |
upper1)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment