/*
* Copyright (c) 2011-2016, Peter Abeles. All Rights Reserved.
*
* This file is part of BoofCV (http://boofcv.org).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package boofcv.demonstrations.feature.flow;
import boofcv.abst.distort.FDistort;
import boofcv.abst.flow.DenseOpticalFlow;
import boofcv.factory.flow.FactoryDenseOpticalFlow;
import boofcv.gui.PanelGridPanel;
import boofcv.gui.SelectAlgorithmAndInputPanel;
import boofcv.gui.feature.VisualizeOpticalFlow;
import boofcv.gui.image.AnimatePanel;
import boofcv.gui.image.ImagePanel;
import boofcv.gui.image.ShowImages;
import boofcv.io.PathLabel;
import boofcv.io.ProgressMonitorThread;
import boofcv.io.UtilIO;
import boofcv.io.image.ConvertBufferedImage;
import boofcv.struct.flow.ImageFlow;
import boofcv.struct.image.GrayF32;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
/**
* Displays dense optical flow
*
* @author Peter Abeles
*/
public class DenseFlowApp
extends SelectAlgorithmAndInputPanel
{
// displays intensity image
PanelGridPanel gui;
ImagePanel flowPanel;
AnimatePanel animationPanel;
// converted input image
GrayF32 unscaled = new GrayF32(1,1);
GrayF32 input0 = new GrayF32(1,1);
GrayF32 input1 = new GrayF32(1,1);
ImageFlow flow = new ImageFlow(1,1);
// if it has processed an image or not
boolean processImage = false;
boolean hasInputImage = false;
DenseOpticalFlow denseFlow;
BufferedImage converted0,converted1,visualized;
public DenseFlowApp() {
super(1);
Class T = GrayF32.class;
addAlgorithm(0, "KLT", FactoryDenseOpticalFlow.flowKlt(null,6,T,T));
addAlgorithm(0, "Region", FactoryDenseOpticalFlow.region(null,T));
addAlgorithm(0, "Horn-Schunck-Pyramid",FactoryDenseOpticalFlow.hornSchunckPyramid(null,GrayF32.class));
addAlgorithm(0, "Brox",FactoryDenseOpticalFlow.broxWarping(null, GrayF32.class));
addAlgorithm(0, "Horn-Schunck",FactoryDenseOpticalFlow.hornSchunck(null, GrayF32.class));
animationPanel = new AnimatePanel(200,null);
flowPanel = new ImagePanel();
gui = new PanelGridPanel(2,animationPanel,flowPanel);
animationPanel.start();
setMainGUI(gui);
}
@Override
public synchronized void setActiveAlgorithm(int indexFamily, String name, Object cookie) {
denseFlow = (DenseOpticalFlow)cookie;
process();
}
@Override
public synchronized void changeInput(String name, int index) {
BufferedImage image0 = media.openImage(inputRefs.get(index).getPath(0));
BufferedImage image1 = media.openImage(inputRefs.get(index).getPath(1) );
// process at 1/2 resolution to make it faster
unscaled.reshape(image0.getWidth(),image1.getHeight());
input0.reshape(unscaled.width/2,unscaled.height/2);
input1.reshape(unscaled.width/2,unscaled.height/2);
flow.reshape(unscaled.width/2,unscaled.height/2);
ConvertBufferedImage.convertFrom(image0, unscaled, false);
new FDistort(unscaled,input0).scaleExt().apply();
ConvertBufferedImage.convertFrom(image1, unscaled, false);
new FDistort(unscaled,input1).scaleExt().apply();
converted0 = new BufferedImage(input0.width,input0.height,BufferedImage.TYPE_INT_RGB);
converted1 = new BufferedImage(input0.width,input0.height,BufferedImage.TYPE_INT_RGB);
visualized = new BufferedImage(input0.width,input0.height,BufferedImage.TYPE_INT_RGB);
ConvertBufferedImage.convertTo(input0, converted0, true);
ConvertBufferedImage.convertTo(input1, converted1, true);
hasInputImage = true;
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
flowPanel.setPreferredSize(new Dimension(input0.width,input0.height));
flowPanel.setBufferedImage(visualized);
animationPanel.setPreferredSize(new Dimension(input0.width,input0.height));
animationPanel.setAnimation(converted0,converted1);
gui.revalidate();
}
});
doRefreshAll();
}
@Override
public void loadConfigurationFile(String fileName) {}
@Override
public void refreshAll(Object[] cookies) {
setActiveAlgorithm(0,null,cookies[0]);
}
private synchronized void process() {
if( hasInputImage && denseFlow != null ) {
ProcessThread progress = new ProcessThread(this);
progress.start();
denseFlow.process(input0, input1, flow);
progress.stopThread();
VisualizeOpticalFlow.colorized(flow, 10, visualized);
gui.repaint();
processImage = true;
}
}
@Override
public boolean getHasProcessedImage() {
return processImage;
}
/**
* Displays a progress monitor and updates its state periodically
*/
public class ProcessThread extends ProgressMonitorThread
{
public ProcessThread( JComponent owner ) {
super(new ProgressMonitor(owner, "Computing Flow", "", 0, 100));
}
@Override
public void doRun() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
monitor.setProgress(0);
}});
}
}
public static void main( String args[] ) {
DenseFlowApp app = new DenseFlowApp();
// app.setBaseDirectory(UtilIO.pathExample("denseflow/");
// app.loadInputData(UtilIO.pathExample("denseflow/denseflow.txt");
java.util.List inputs = new ArrayList();
inputs.add(new PathLabel("urban", UtilIO.pathExample("denseflow/Urban2_07.png"), UtilIO.pathExample("denseflow/Urban2_08.png")));
inputs.add(new PathLabel("dog",UtilIO.pathExample("denseflow/dogdance07.png"),UtilIO.pathExample("denseflow/dogdance08.png")));
inputs.add(new PathLabel("grove",UtilIO.pathExample("denseflow/Grove2_07.png"),UtilIO.pathExample("denseflow/Grove2_08.png")));
app.setInputList(inputs);
// wait for it to process one image so that the size isn't all screwed up
while( !app.getHasProcessedImage() ) {
Thread.yield();
}
ShowImages.showWindow(app,"Dense Optical Flow",true);
}
}
Ads help maintain this website.