@Override public PointTracker<GrayF32> createTracker() { DescribePointBrief<GrayF32> brief = FactoryDescribePointAlgs.brief( FactoryBriefDefinition.gaussian2(new Random(123), 16, 512), FactoryBlurFilter.gaussian(GrayF32.class, 0, 4)); GeneralFeatureDetector<GrayF32, GrayF32> corner = FactoryDetectPoint.createShiTomasi( new ConfigGeneralDetector(100, 2, 0), false, GrayF32.class); InterestPointDetector<GrayF32> detector = FactoryInterestPoint.wrapPoint(corner, 1, GrayF32.class, GrayF32.class); ScoreAssociateHamming_B score = new ScoreAssociateHamming_B(); AssociateDescription<TupleDesc_B> association = FactoryAssociation.greedy(score, 400, true); PointTracker<GrayF32> pointTracker = FactoryPointTracker.combined( detector, null, new WrapDescribeBrief<>(brief, GrayF32.class), association, null, 20, GrayF32.class); return pointTracker; }
protected MonocularPlaneVisualOdometry<ImageUInt8> createAlgorithm() { PkltConfig config = new PkltConfig(); config.pyramidScaling = new int[] {1, 2, 4, 8}; config.templateRadius = 3; ConfigGeneralDetector configDetector = new ConfigGeneralDetector(600, 3, 1); PointTracker<ImageUInt8> tracker = FactoryPointTracker.klt(config, configDetector, ImageUInt8.class, ImageSInt16.class); return FactoryVisualOdometry.monoPlaneInfinity( 50, 2, 1.5, 300, tracker, ImageType.single(ImageUInt8.class)); }
private StitchingFromMotion2D<GrayU8, Affine2D_F64> createStabilization() { ConfigGeneralDetector config = new ConfigGeneralDetector(); config.maxFeatures = 150; config.threshold = 40; config.radius = 3; PointTracker<GrayU8> tracker = FactoryPointTracker.klt(new int[] {1, 2, 4}, config, 3, GrayU8.class, GrayS16.class); ImageMotion2D<GrayU8, Affine2D_F64> motion = FactoryMotion2D.createMotion2D( 100, 1.5, 2, 40, 0.5, 0.6, false, tracker, new Affine2D_F64()); return FactoryMotion2D.createVideoStitch(0.2, motion, ImageType.single(GrayU8.class)); }
public static void main(String[] args) { // Example with a moving camera. Highlights why motion estimation is sometimes required String fileName = UtilIO.pathExample("tracking/chipmunk.mjpeg"); // Camera has a bit of jitter in it. Static kinda works but motion reduces false positives // String fileName = UtilIO.pathExample("background/horse_jitter.mp4"); // Comment/Uncomment to switch input image type ImageType imageType = ImageType.single(GrayF32.class); // ImageType imageType = ImageType.il(3, InterleavedF32.class); // ImageType imageType = ImageType.il(3, InterleavedU8.class); // Configure the feature detector ConfigGeneralDetector confDetector = new ConfigGeneralDetector(); confDetector.threshold = 10; confDetector.maxFeatures = 300; confDetector.radius = 6; // Use a KLT tracker PointTracker tracker = FactoryPointTracker.klt(new int[] {1, 2, 4, 8}, confDetector, 3, GrayF32.class, null); // This estimates the 2D image motion ImageMotion2D<GrayF32, Homography2D_F64> motion2D = FactoryMotion2D.createMotion2D( 500, 0.5, 3, 100, 0.6, 0.5, false, tracker, new Homography2D_F64()); ConfigBackgroundBasic configBasic = new ConfigBackgroundBasic(30, 0.005f); // Configuration for Gaussian model. Note that the threshold changes depending on the number of // image bands // 12 = gray scale and 40 = color ConfigBackgroundGaussian configGaussian = new ConfigBackgroundGaussian(12, 0.001f); configGaussian.initialVariance = 64; configGaussian.minimumDifference = 5; // Comment/Uncomment to switch background mode BackgroundModelMoving background = FactoryBackgroundModel.movingBasic( configBasic, new PointTransformHomography_F32(), imageType); // FactoryBackgroundModel.movingGaussian(configGaussian, new PointTransformHomography_F32(), // imageType); MediaManager media = DefaultMediaManager.INSTANCE; SimpleImageSequence video = media.openVideo(fileName, background.getImageType()); // media.openCamera(null,640,480,background.getImageType()); // ====== Initialize Images // storage for segmented image. Background = 0, Foreground = 1 GrayU8 segmented = new GrayU8(video.getNextWidth(), video.getNextHeight()); // Grey scale image that's the input for motion estimation GrayF32 grey = new GrayF32(segmented.width, segmented.height); // coordinate frames Homography2D_F32 firstToCurrent32 = new Homography2D_F32(); Homography2D_F32 homeToWorld = new Homography2D_F32(); homeToWorld.a13 = grey.width / 2; homeToWorld.a23 = grey.height / 2; // Create a background image twice the size of the input image. Tell it that the home is in the // center background.initialize(grey.width * 2, grey.height * 2, homeToWorld); BufferedImage visualized = new BufferedImage(segmented.width, segmented.height, BufferedImage.TYPE_INT_RGB); ImageGridPanel gui = new ImageGridPanel(1, 2); gui.setImages(visualized, visualized); ShowImages.showWindow(gui, "Detections", true); double fps = 0; double alpha = 0.01; // smoothing factor for FPS while (video.hasNext()) { ImageBase input = video.next(); long before = System.nanoTime(); GConvertImage.convert(input, grey); if (!motion2D.process(grey)) { throw new RuntimeException("Should handle this scenario"); } Homography2D_F64 firstToCurrent64 = motion2D.getFirstToCurrent(); UtilHomography.convert(firstToCurrent64, firstToCurrent32); background.segment(firstToCurrent32, input, segmented); background.updateBackground(firstToCurrent32, input); long after = System.nanoTime(); fps = (1.0 - alpha) * fps + alpha * (1.0 / ((after - before) / 1e9)); VisualizeBinaryData.renderBinary(segmented, false, visualized); gui.setImage(0, 0, (BufferedImage) video.getGuiImage()); gui.setImage(0, 1, visualized); gui.repaint(); System.out.println("FPS = " + fps); try { Thread.sleep(5); } catch (InterruptedException e) { } } }