The following Processing codes demonstrate the use of the OpenCV Features2D to detect key points from the webcam image. It is the first part of a more complex task to identify 3D motion from a 2D image.
import processing.video.*; import java.util.*; import java.nio.*; import org.opencv.core.Core; import org.opencv.core.Mat; import org.opencv.core.CvType; import org.opencv.imgproc.Imgproc; import org.opencv.features2d.Features2d; import org.opencv.features2d.FeatureDetector; import org.opencv.core.MatOfKeyPoint; import org.opencv.features2d.KeyPoint; final float DELTA = 10.0; Capture cap; byte [] bArray; int [] iArray; int pixCnt1, pixCnt2; FeatureDetector detector; void setup() { size(640, 480); background(0); // Define and initialise the default capture device. cap = new Capture(this, width, height); cap.start(); // Load the OpenCV native library. System.loadLibrary(Core.NATIVE_LIBRARY_NAME); println(Core.VERSION); // pixCnt1 is the number of bytes in the pixel buffer. // pixCnt2 is the number of integers in the PImage pixels buffer. pixCnt1 = width*height*4; pixCnt2 = width*height; // bArray is the temporary byte array buffer for OpenCV cv::Mat. // iArray is the temporary integer array buffer for PImage pixels. bArray = new byte[pixCnt1]; iArray = new int[pixCnt2]; detector = FeatureDetector.create(FeatureDetector.ORB); noFill(); stroke(255, 255, 0, 180); } void draw() { if (cap.available()) { cap.read(); } else { return; } image(cap, 0, 0); // Copy the webcam image to the temporary integer array iArray. arrayCopy(cap.pixels, iArray); // Define the temporary Java byte and integer buffers. // They share the same storage. ByteBuffer bBuf = ByteBuffer.allocate(pixCnt1); IntBuffer iBuf = bBuf.asIntBuffer(); // Copy the webcam image to the byte buffer iBuf. iBuf.put(iArray); // Copy the webcam image to the byte array bArray. bBuf.get(bArray); // Create the OpenCV cv::Mat. Mat m1 = new Mat(height, width, CvType.CV_8UC4); // Initialise the matrix m1 with content from bArray. m1.put(0, 0, bArray); // Prepare the grayscale matrix. Mat m3 = new Mat(height, width, CvType.CV_8UC1); Imgproc.cvtColor(m1, m3, Imgproc.COLOR_BGRA2GRAY); MatOfKeyPoint keypoints = new MatOfKeyPoint(); detector.detect(m3, keypoints); KeyPoint [] points = keypoints.toArray(); ArrayList<KeyPoint> pList = new ArrayList<KeyPoint>(); pList.add(points[0]); // Remove the keypoints that are closed together. for (int i=1; i<points.length; i++) { boolean done = true; for (int j=0; j<pList.size(); j++) { float d = dist((float)points[i].pt.x, (float)points[i].pt.y, (float)pList.get(j).pt.x, (float)pList.get(j).pt.y); if (d > DELTA) { continue; } else { done = false; } } if (done) { pList.add(points[i]); } } for (int i=0; i<pList.size(); i++) { ellipse((float)pList.get(i).pt.x, (float)pList.get(i).pt.y, pList.get(i).size, pList.get(i).size); if (pList.get(i).angle != -1) { float angle = 360.0 - pList.get(i).angle; float tx = (float)pList.get(i).pt.x + pList.get(i).size*cos(radians(angle))/2.0; float ty = (float)pList.get(i).pt.y + pList.get(i).size*sin(radians(angle))/2.0; line(tx, ty, (float)pList.get(i).pt.x, (float)pList.get(i).pt.y); } } keypoints.release(); text("Frame Rate: " + round(frameRate), 500, 50); } |