![JAR search and dependency download from the Maven repository](/logo.png)
boofcv.gui.feature.CompareTwoImagePanel Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of visualize Show documentation
Show all versions of visualize Show documentation
BoofCV is an open source Java library for real-time computer vision and robotics applications.
The newest version!
/*
* 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.gui.feature;
import georegression.geometry.UtilPoint2D_F64;
import georegression.struct.point.Point2D_F64;
import georegression.struct.point.Point2D_I32;
import org.ddogleg.struct.GrowQueue_I32;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
/**
* Panel for displaying two images next to each other separated by a border.
*
* @author Peter Abeles
*/
public abstract class CompareTwoImagePanel extends JPanel implements MouseListener , MouseMotionListener{
// how close a click needs to be to a point
private double clickDistance = 20;
// list of features in both images
protected List leftPts,rightPts;
// draw a selected pair
List selected = new ArrayList<>();
protected boolean selectedIsLeft;
// can it select more than one?
protected boolean selectRegion;
// size of the border between the images
protected int borderSize;
// left and right window information
protected BufferedImage leftImage,rightImage;
protected double scaleLeft,scaleRight;
// where it first clicked when selecting a region
protected Point2D_I32 firstClick;
// current position of the mouse while being dragged
protected Point2D_I32 mousePosition = new Point2D_I32();
public CompareTwoImagePanel(int borderSize , boolean canSelectRegion) {
this.borderSize = borderSize;
this.selectRegion = canSelectRegion;
addMouseListener(this);
addMouseMotionListener(this);
}
public void setLocation( List leftPts , List rightPts) {
this.leftPts = leftPts;
this.rightPts = rightPts;
selected.clear();
}
/**
* Sets the internal images. Not thread safe.
*
* @param leftImage
* @param rightImage
*/
public synchronized void setImages(BufferedImage leftImage , BufferedImage rightImage ) {
this.leftImage = leftImage;
this.rightImage = rightImage;
int width = leftImage.getWidth() + rightImage.getWidth()+borderSize;
int height = Math.max(leftImage.getHeight(),rightImage.getHeight());
setPreferredSize(new Dimension(width,height));
}
@Override
public synchronized void paintComponent(Graphics g) {
super.paintComponent(g);
if( leftImage == null || rightImage == null )
return;
computeScales();
Graphics2D g2 = (Graphics2D)g;
// location in the current frame, taking in account the scale of each image
int x1 = (int)(scaleLeft*leftImage.getWidth());
int x2 = x1+borderSize;
int x3 = x2+(int)(scaleRight*rightImage.getWidth());
int y1 = (int)(scaleLeft*leftImage.getHeight());
int y2 = (int)(scaleRight*rightImage.getHeight());
// draw the background images
g2.drawImage(leftImage,0,0,x1,y1,0,0,leftImage.getWidth(),leftImage.getHeight(),null);
g2.drawImage(rightImage,x2,0,x3,y2,0,0,rightImage.getWidth(),rightImage.getHeight(),null);
drawFeatures(g2,scaleLeft,0,0,scaleRight,x2,0);
// draw the selected region
if( selectRegion && firstClick != null ) {
int x0 = mousePosition.getX() < firstClick.x ? mousePosition.getX() : firstClick.x;
x1 = mousePosition.getX() >= firstClick.x ? mousePosition.getX() : firstClick.x;
int y0 = mousePosition.getY() < firstClick.y ? mousePosition.getY() : firstClick.y;
y1 = mousePosition.getY() >= firstClick.y ? mousePosition.getY() : firstClick.y;
g2.setColor(Color.WHITE);
g2.setStroke(new BasicStroke(3));
g2.drawRect(x0,y0,x1-x0,y1-y0);
g2.setColor(Color.BLACK);
g2.setStroke(new BasicStroke(1));
g2.drawRect(x0,y0,x1-x0,y1-y0);
}
}
/**
* Implement this function to draw features related to each image.
*
* @param scaleLeft Scale of left image.
* @param leftX Left image (0,0) coordinate.
* @param leftY Left image (0,0) coordinate.
* @param scaleRight Scale of right image.
* @param rightX Right image (0,0) coordinate.
* @param rightY Right image (0,0) coordinate.
*/
protected abstract void drawFeatures( Graphics2D g2 ,
double scaleLeft , int leftX , int leftY ,
double scaleRight , int rightX , int rightY );
/**
* Compute individually how each image will be scaled
*/
private void computeScales() {
int width = getWidth();
int height = getHeight();
width = (width-borderSize)/2;
// compute the scale factor for each image
scaleLeft = scaleRight = 1;
if( leftImage.getWidth() > width || leftImage.getHeight() > height ) {
double scaleX = (double)width/(double)leftImage.getWidth();
double scaleY = (double)height/(double)leftImage.getHeight();
scaleLeft = Math.min(scaleX,scaleY);
}
if( rightImage.getWidth() > width || rightImage.getHeight() > height ) {
double scaleX = (double)width/(double)rightImage.getWidth();
double scaleY = (double)height/(double)rightImage.getHeight();
scaleRight = Math.min(scaleX,scaleY);
}
}
@Override
public void mouseClicked(MouseEvent e) {
firstClick = null;
selected.clear();
if( e.getClickCount() > 1 ) {
repaint();
return;
}
int leftEndX = (int)(scaleLeft*leftImage.getWidth());
int rightBeginX = leftEndX + borderSize;
if( e.getX() < leftEndX ) {
selectedIsLeft = true;
int x = (int)(e.getX()/scaleLeft);
int y = (int)(e.getY()/scaleLeft);
findBestPoints(x, y, leftPts , selected );
} else if( e.getX() >= rightBeginX ) {
selectedIsLeft = false;
int x = (int)((e.getX()-rightBeginX)/scaleRight);
int y = (int)(e.getY()/scaleRight);
findBestPoints(x, y, rightPts , selected );
}
// System.out.println("selected index "+selectedIndex);
repaint();
}
private void findBestPoints(int x, int y, List pts , List selected ) {
double bestDist = clickDistance*clickDistance;
GrowQueue_I32 bestIndexes = new GrowQueue_I32(20);
for( int i = 0; i < pts.size(); i++ ) {
if( !isValidPoint(i) )
continue;
Point2D_F64 p = pts.get(i);
double d = UtilPoint2D_F64.distanceSq(p.x, p.y, x, y);
if( d < bestDist ) {
bestDist = d;
bestIndexes.reset();
bestIndexes.add(i);
} else if( Math.abs(d - bestDist) < 0.01 ) {
bestIndexes.add(i);
}
}
if( bestIndexes.size() > 0 ) {
int indexRight = bestIndexes.get(0);
}
for (int i = 0; i < bestIndexes.size(); i++) {
selected.add(bestIndexes.get(i));
}
}
protected abstract boolean isValidPoint( int index );
@Override
public void mousePressed(MouseEvent e) {
if( selectRegion )
firstClick = new Point2D_I32(e.getX(),e.getY());
}
@Override
public void mouseReleased(MouseEvent e) {
if( !selectRegion ) {
return;
}
// adjust the selected region for scale and the image that was selected
int leftEndX = (int)(scaleLeft*leftImage.getWidth());
int rightBeginX = leftEndX + borderSize;
selectedIsLeft = e.getX() < leftEndX;
int x0 = e.getX() < firstClick.x ? e.getX() : firstClick.x;
int x1 = e.getX() >= firstClick.x ? e.getX() : firstClick.x;
int y0 = e.getY() < firstClick.y ? e.getY() : firstClick.y;
int y1 = e.getY() >= firstClick.y ? e.getY() : firstClick.y;
double scale = selectedIsLeft ? scaleLeft : scaleRight;
if( selectedIsLeft) {
x0 /= scale;
x1 /= scale;
} else {
x0 = (int)((x0 - rightBeginX)/scale);
x1 = (int)((x1 - rightBeginX)/scale);
}
y0 /= scale;
y1 /= scale;
// find all the points in the region
if( selectedIsLeft ) {
findPointsInRegion(x0,y0,x1,y1,leftPts);
} else {
findPointsInRegion(x0,y0,x1,y1,rightPts);
}
// reset the selector
firstClick = null;
repaint();
}
private void findPointsInRegion( int x0 , int y0 , int x1 , int y1 , List pts )
{
selected.clear();
for( int i = 0; i < pts.size(); i++ ) {
if( !isValidPoint(i) )
continue;
Point2D_F64 p = pts.get(i);
if( p.x >= x0 && p.x < x1 && p.y >= y0 && p.y < y1 ) {
selected.add(i);
}
}
}
@Override
public void mouseEntered(MouseEvent e) {}
@Override
public void mouseExited(MouseEvent e) {}
@Override
public void mouseDragged(MouseEvent e){
if( selectRegion ) {
mousePosition.x = e.getX();
mousePosition.y = e.getY();
repaint();
}
}
@Override
public void mouseMoved(MouseEvent e){}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy