/** * * @author greg (at) myrobotlab.org * * This file is part of MyRobotLab (http://myrobotlab.org). * * MyRobotLab is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version (subject to the "Classpath" exception * as provided in the LICENSE.txt file that accompanied this code). * * MyRobotLab is distributed in the hope that it will be useful or fun, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * All libraries in thirdParty bundle are subject to their own license * requirements - please refer to http://myrobotlab.org/libraries for * details. * * Enjoy ! * * */ package org.myrobotlab.opencv; import static org.bytedeco.javacpp.helper.opencv_core.CV_RGB; import static org.bytedeco.javacpp.opencv_core.IPL_DEPTH_32F; import static org.bytedeco.javacpp.opencv_core.cvCopy; import static org.bytedeco.javacpp.opencv_core.cvCreateImage; import static org.bytedeco.javacpp.opencv_core.cvMinMaxLoc; import static org.bytedeco.javacpp.opencv_core.cvPoint; import static org.bytedeco.javacpp.opencv_core.cvResetImageROI; import static org.bytedeco.javacpp.opencv_core.cvScalar; import static org.bytedeco.javacpp.opencv_core.cvSetImageROI; import static org.bytedeco.javacpp.opencv_core.cvSize; import static org.bytedeco.javacpp.opencv_imgproc.CV_FONT_HERSHEY_PLAIN; import static org.bytedeco.javacpp.opencv_imgproc.CV_TM_SQDIFF; import static org.bytedeco.javacpp.opencv_imgproc.cvFont; import static org.bytedeco.javacpp.opencv_imgproc.cvMatchTemplate; import static org.bytedeco.javacpp.opencv_imgproc.cvPutText; import static org.bytedeco.javacpp.opencv_imgproc.cvRectangle; import org.bytedeco.javacpp.DoublePointer; import org.bytedeco.javacpp.opencv_core.CvPoint; import org.bytedeco.javacpp.opencv_core.CvRect; import org.bytedeco.javacpp.opencv_core.IplImage; import org.bytedeco.javacpp.opencv_imgproc.CvFont; import org.myrobotlab.logging.LoggerFactory; import org.myrobotlab.service.OpenCV; import org.slf4j.Logger; // TODO - http://opencv.willowgarage.com/wiki/FastMatchTemplate // FIXME - get template from exterior source // FIXME - named inputs output - defaults "created" filterName_input filternName_output - // must create a "input filter (non filter) and a non-filter output // Think about the difference between publishing vs blocking on data from different thread // its probably best that this thread run unhindered and therefore "publishing" // publish list ! - source should be <opencv>_<filtername>_<output/input?> public class OpenCVFilterMatchTemplate extends OpenCVFilter { private static final long serialVersionUID = 1L; public final static Logger log = LoggerFactory.getLogger(OpenCVFilterMatchTemplate.class.getCanonicalName()); double[] minVal = new double[1]; double[] maxVal = new double[1]; transient public IplImage template = null; transient IplImage res = null; transient CvPoint minLoc = new CvPoint(); transient CvPoint maxLoc = new CvPoint(); transient CvPoint tempRect0 = new CvPoint(); transient CvPoint tempRect1 = new CvPoint(); transient CvPoint centeroid = cvPoint(0, 0); int clickCount = 0; int x0, y0, x1, y1; public CvRect rect = new CvRect(); public boolean makeTemplate = false; CvPoint textpt = cvPoint(10, 20); private CvFont font = cvFont(CV_FONT_HERSHEY_PLAIN); public int matchRatio = Integer.MAX_VALUE; boolean isTracking = false; public OpenCVFilterMatchTemplate() { super(); } public OpenCVFilterMatchTemplate(String name) { super(name); } @Override public void imageChanged(IplImage image) { // TODO Auto-generated method stub } @Override public IplImage process(IplImage image, OpenCVData data) { // cvMatchTemplate(iamge, arg1, arg2, arg3); /* * if (res == null && template != null) // || dim size change { res = * cvCreateImage( cvSize( image.width() - template.width() + 1, * image.height() - template.height() + 1), IPL_DEPTH_32F, 1 ); } */ // CV_TM_CCOEFF_NORMED // cv.cvMatchTemplate(arg0, arg1, arg2, arg3); if (template != null && res != null) { // TODO - DISPLAY RES SO THAT RESULTS FORM DIFFERENT FN's CAN BE // EXAMINED cvMatchTemplate(image, template, res, CV_TM_SQDIFF); // cvNormalize( ftmp[i], ftmp[i], 1, 0, CV_MINMAX ); cvMinMaxLoc(res, new DoublePointer(minVal), new DoublePointer(maxVal), minLoc, maxLoc, null); tempRect0.x(minLoc.x()); tempRect0.y(minLoc.y()); tempRect1.x(minLoc.x() + template.width()); tempRect1.y(minLoc.y() + template.height()); } if (makeTemplate) { makeTemplate = false; template = cvCreateImage(cvSize(rect.width(), rect.height()), image.depth(), image.nChannels()); /* copy ROI to subimg */ cvSetImageROI(image, rect); cvCopy(image, template, null); cvResetImageROI(image); invoke("publishTemplate", name, OpenCV.IplImageToBufferedImage(template), 0); invoke("publishIplImageTemplate", template); // FYI - // IplImage // is not // serializable res = cvCreateImage(cvSize(image.width() - template.width() + 1, image.height() - template.height() + 1), IPL_DEPTH_32F, 1); } if (template != null) { // String text = "" + minVal[0]; // textpt.y(20); // cvPutText(image, text, textpt, font, CV_RGB(254, 254, 254)); textpt.y(20); matchRatio = (int) (minVal[0] / ((tempRect1.x() - tempRect0.x()) * (tempRect1.y() - tempRect0.y()))); cvPutText(image, "" + matchRatio, textpt, font, CV_RGB(254, 254, 254)); if (matchRatio < 500) { // draw rectangle cvRectangle(image, tempRect0, tempRect1, cvScalar(255, 255, 255, 0), 1, 0, 0); textpt.y(30); cvPutText(image, "locked", textpt, font, CV_RGB(254, 254, 254)); centeroid.x(tempRect0.x() + ((tempRect1.x() - tempRect0.x()) / 2)); centeroid.y(tempRect0.y() + ((tempRect1.y() - tempRect0.y()) / 2)); invoke("publish", centeroid); if (isTracking != true) // message clutter optimization { invoke("isTracking", true); } isTracking = true; } else { if (isTracking != false) { invoke("isTracking", false); } isTracking = false; } } // if template != null return image; } public void samplePoint(Float x, Float y) { samplePoint((int) (x * width), (int) (y * height)); } public void samplePoint(Integer x, Integer y) { // MouseEvent me = (MouseEvent)params[0]; // if (event.getButton() == 1) { if (clickCount % 2 == 0) { x0 = x; y0 = y; } else { x1 = x; y1 = y; rect.x(x0); rect.y(y0); rect.width(Math.abs(x1 - x0)); rect.height(Math.abs(y1 - y0)); makeTemplate = true; } // } ++clickCount; } }