The objective is to: *Reduce greatly the number of lines of code in the Java codes; *Make it easy for Java users to add a trackbar and show the results; *Get the code more similar between C++, Java and Python, making the tutorials more uniform.pull/8847/head
parent
e5aa213554
commit
6512a4b7e3
3 changed files with 330 additions and 1 deletions
@ -0,0 +1,193 @@ |
|||||||
|
package org.opencv.highgui; |
||||||
|
|
||||||
|
import org.opencv.core.Mat; |
||||||
|
|
||||||
|
import javax.swing.*; |
||||||
|
import java.awt.*; |
||||||
|
import java.awt.event.KeyEvent; |
||||||
|
import java.awt.event.KeyListener; |
||||||
|
import java.awt.image.BufferedImage; |
||||||
|
import java.awt.image.DataBufferByte; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.Iterator; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.concurrent.CountDownLatch; |
||||||
|
import java.util.concurrent.TimeUnit; |
||||||
|
|
||||||
|
/** |
||||||
|
* This class was designed for use in Java applications |
||||||
|
* to recreate the OpenCV HighGui functionalities. |
||||||
|
*/ |
||||||
|
public final class HighGui { |
||||||
|
|
||||||
|
// Constants for namedWindow
|
||||||
|
public final static int WINDOW_NORMAL = ImageWindow.WINDOW_NORMAL; |
||||||
|
public final static int WINDOW_AUTOSIZE = ImageWindow.WINDOW_AUTOSIZE; |
||||||
|
|
||||||
|
// Control Variables
|
||||||
|
public static int n_closed_windows = 0; |
||||||
|
public static int pressedKey = -1; |
||||||
|
public static CountDownLatch latch = new CountDownLatch(1); |
||||||
|
|
||||||
|
// Windows Map
|
||||||
|
public static Map<String, ImageWindow> windows = new HashMap<String, ImageWindow>(); |
||||||
|
|
||||||
|
public static void namedWindow(String winname) { |
||||||
|
namedWindow(winname, HighGui.WINDOW_AUTOSIZE); |
||||||
|
} |
||||||
|
|
||||||
|
public static void namedWindow(String winname, int flag) { |
||||||
|
ImageWindow newWin = new ImageWindow(winname, flag); |
||||||
|
if (windows.get(winname) == null) windows.put(winname, newWin); |
||||||
|
} |
||||||
|
|
||||||
|
public static void imshow(String winname, Mat img) { |
||||||
|
if (img.empty()) { |
||||||
|
System.err.println("Error: Empty image in imshow"); |
||||||
|
System.exit(-1); |
||||||
|
} else { |
||||||
|
ImageWindow tmpWindow = windows.get(winname); |
||||||
|
if (tmpWindow == null) { |
||||||
|
ImageWindow newWin = new ImageWindow(winname, img); |
||||||
|
windows.put(winname, newWin); |
||||||
|
} else { |
||||||
|
tmpWindow.setMat(img); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static Image toBufferedImage(Mat m) { |
||||||
|
int type = BufferedImage.TYPE_BYTE_GRAY; |
||||||
|
|
||||||
|
if (m.channels() > 1) { |
||||||
|
type = BufferedImage.TYPE_3BYTE_BGR; |
||||||
|
} |
||||||
|
|
||||||
|
int bufferSize = m.channels() * m.cols() * m.rows(); |
||||||
|
byte[] b = new byte[bufferSize]; |
||||||
|
m.get(0, 0, b); // get all the pixels
|
||||||
|
BufferedImage image = new BufferedImage(m.cols(), m.rows(), type); |
||||||
|
|
||||||
|
final byte[] targetPixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData(); |
||||||
|
System.arraycopy(b, 0, targetPixels, 0, b.length); |
||||||
|
|
||||||
|
return image; |
||||||
|
} |
||||||
|
|
||||||
|
public static JFrame createJFrame(String title, int flag) { |
||||||
|
JFrame frame = new JFrame(title); |
||||||
|
|
||||||
|
frame.addWindowListener(new java.awt.event.WindowAdapter() { |
||||||
|
@Override |
||||||
|
public void windowClosing(java.awt.event.WindowEvent windowEvent) { |
||||||
|
n_closed_windows++; |
||||||
|
if (n_closed_windows == windows.size()) latch.countDown(); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
frame.addKeyListener(new KeyListener() { |
||||||
|
@Override |
||||||
|
public void keyTyped(KeyEvent e) { |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void keyReleased(KeyEvent e) { |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void keyPressed(KeyEvent e) { |
||||||
|
pressedKey = e.getKeyCode(); |
||||||
|
latch.countDown(); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
if (flag == WINDOW_AUTOSIZE) frame.setResizable(false); |
||||||
|
|
||||||
|
return frame; |
||||||
|
} |
||||||
|
|
||||||
|
public static void waitKey(){ |
||||||
|
waitKey(0); |
||||||
|
} |
||||||
|
|
||||||
|
public static int waitKey(int delay) { |
||||||
|
// Reset control values
|
||||||
|
latch = new CountDownLatch(1); |
||||||
|
n_closed_windows = 0; |
||||||
|
pressedKey = -1; |
||||||
|
|
||||||
|
// If there are no windows to be shown return
|
||||||
|
if (windows.isEmpty()) { |
||||||
|
System.err.println("Error: waitKey must be used after an imshow"); |
||||||
|
System.exit(-1); |
||||||
|
} |
||||||
|
|
||||||
|
// Remove the unused windows
|
||||||
|
Iterator<Map.Entry<String, |
||||||
|
ImageWindow>> iter = windows.entrySet().iterator(); |
||||||
|
while (iter.hasNext()) { |
||||||
|
Map.Entry<String, |
||||||
|
ImageWindow> entry = iter.next(); |
||||||
|
ImageWindow win = entry.getValue(); |
||||||
|
if (win.alreadyUsed) { |
||||||
|
iter.remove(); |
||||||
|
win.frame.dispose(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// (if) Create (else) Update frame
|
||||||
|
for (ImageWindow win : windows.values()) { |
||||||
|
|
||||||
|
if (win.img != null) { |
||||||
|
|
||||||
|
ImageIcon icon = new ImageIcon(toBufferedImage(win.img)); |
||||||
|
|
||||||
|
if (win.lbl == null) { |
||||||
|
JFrame frame = createJFrame(win.name, win.flag); |
||||||
|
JLabel lbl = new JLabel(icon); |
||||||
|
win.setFrameLabelVisible(frame, lbl); |
||||||
|
} else { |
||||||
|
win.lbl.setIcon(icon); |
||||||
|
} |
||||||
|
} else { |
||||||
|
System.err.println("Error: no imshow associated with" + " namedWindow: \"" + win.name + "\""); |
||||||
|
System.exit(-1); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
try { |
||||||
|
if (delay == 0) { |
||||||
|
latch.await(); |
||||||
|
} else { |
||||||
|
latch.await(delay, TimeUnit.MILLISECONDS); |
||||||
|
} |
||||||
|
} catch (InterruptedException e) { |
||||||
|
e.printStackTrace(); |
||||||
|
} |
||||||
|
|
||||||
|
// Set all windows as already used
|
||||||
|
for (ImageWindow win : windows.values()) |
||||||
|
win.alreadyUsed = true; |
||||||
|
|
||||||
|
return pressedKey; |
||||||
|
} |
||||||
|
|
||||||
|
public static void destroyWindow(String winname) { |
||||||
|
ImageWindow tmpWin = windows.get(winname); |
||||||
|
if (tmpWin != null) windows.remove(winname); |
||||||
|
} |
||||||
|
|
||||||
|
public static void destroyAllWindows() { |
||||||
|
windows.clear(); |
||||||
|
} |
||||||
|
|
||||||
|
public static void resizeWindow(String winname, int width, int height) { |
||||||
|
ImageWindow tmpWin = windows.get(winname); |
||||||
|
if (tmpWin != null) tmpWin.setNewDimension(width, height); |
||||||
|
} |
||||||
|
|
||||||
|
public static void moveWindow(String winname, int x, int y) { |
||||||
|
ImageWindow tmpWin = windows.get(winname); |
||||||
|
if (tmpWin != null) tmpWin.setNewPosition(x, y); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,132 @@ |
|||||||
|
package org.opencv.highgui; |
||||||
|
|
||||||
|
import org.opencv.core.Mat; |
||||||
|
import org.opencv.core.Size; |
||||||
|
import org.opencv.imgproc.Imgproc; |
||||||
|
|
||||||
|
import javax.swing.*; |
||||||
|
import java.awt.*; |
||||||
|
|
||||||
|
/** |
||||||
|
* This class was designed to create and manipulate |
||||||
|
* the Windows to be used by the HighGui class. |
||||||
|
*/ |
||||||
|
public final class ImageWindow { |
||||||
|
|
||||||
|
public final static int WINDOW_NORMAL = 0; |
||||||
|
public final static int WINDOW_AUTOSIZE = 1; |
||||||
|
|
||||||
|
public String name; |
||||||
|
public Mat img = null; |
||||||
|
public Boolean alreadyUsed = false; |
||||||
|
public Boolean imgToBeResized = false; |
||||||
|
public Boolean windowToBeResized = false; |
||||||
|
public Boolean positionToBeChanged = false; |
||||||
|
public JFrame frame = null; |
||||||
|
public JLabel lbl = null; |
||||||
|
public int flag; |
||||||
|
public int x = -1; |
||||||
|
public int y = -1; |
||||||
|
public int width = -1; |
||||||
|
public int height = -1; |
||||||
|
|
||||||
|
public ImageWindow(String name, Mat img) { |
||||||
|
this.name = name; |
||||||
|
this.img = img; |
||||||
|
this.flag = WINDOW_NORMAL; |
||||||
|
} |
||||||
|
|
||||||
|
public ImageWindow(String name, int flag) { |
||||||
|
this.name = name; |
||||||
|
this.flag = flag; |
||||||
|
} |
||||||
|
|
||||||
|
public static Size keepAspectRatioSize(int original_width, int original_height, int bound_width, int bound_height) { |
||||||
|
|
||||||
|
int new_width = original_width; |
||||||
|
int new_height = original_height; |
||||||
|
|
||||||
|
if (original_width > bound_width) { |
||||||
|
new_width = bound_width; |
||||||
|
new_height = (new_width * original_height) / original_width; |
||||||
|
} |
||||||
|
|
||||||
|
if (new_height > bound_height) { |
||||||
|
new_height = bound_height; |
||||||
|
new_width = (new_height * original_width) / original_height; |
||||||
|
} |
||||||
|
|
||||||
|
return new Size(new_width, new_height); |
||||||
|
} |
||||||
|
|
||||||
|
public void setMat(Mat img) { |
||||||
|
|
||||||
|
this.img = img; |
||||||
|
this.alreadyUsed = false; |
||||||
|
|
||||||
|
if (imgToBeResized) { |
||||||
|
resizeImage(); |
||||||
|
imgToBeResized = false; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
public void setFrameLabelVisible(JFrame frame, JLabel lbl) { |
||||||
|
this.frame = frame; |
||||||
|
this.lbl = lbl; |
||||||
|
|
||||||
|
if (windowToBeResized) { |
||||||
|
lbl.setPreferredSize(new Dimension(width, height)); |
||||||
|
windowToBeResized = false; |
||||||
|
} |
||||||
|
|
||||||
|
if (positionToBeChanged) { |
||||||
|
frame.setLocation(x, y); |
||||||
|
positionToBeChanged = false; |
||||||
|
} |
||||||
|
|
||||||
|
frame.add(lbl); |
||||||
|
frame.pack(); |
||||||
|
frame.setVisible(true); |
||||||
|
} |
||||||
|
|
||||||
|
public void setNewDimension(int width, int height) { |
||||||
|
|
||||||
|
if (this.width != width || this.height != height) { |
||||||
|
this.width = width; |
||||||
|
this.height = height; |
||||||
|
|
||||||
|
if (img != null) { |
||||||
|
resizeImage(); |
||||||
|
} else { |
||||||
|
imgToBeResized = true; |
||||||
|
} |
||||||
|
|
||||||
|
if (lbl != null) { |
||||||
|
lbl.setPreferredSize(new Dimension(width, height)); |
||||||
|
} else { |
||||||
|
windowToBeResized = true; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void setNewPosition(int x, int y) { |
||||||
|
if (this.x != x || this.y != y) { |
||||||
|
this.x = x; |
||||||
|
this.y = y; |
||||||
|
|
||||||
|
if (frame != null) { |
||||||
|
frame.setLocation(x, y); |
||||||
|
} else { |
||||||
|
positionToBeChanged = true; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void resizeImage() { |
||||||
|
if (flag == WINDOW_NORMAL) { |
||||||
|
Size tmpSize = keepAspectRatioSize(img.width(), img.height(), width, height); |
||||||
|
Imgproc.resize(img, img, tmpSize); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue