opencv java 摄像头_使用OpenCV Java创建Windows摄像头扫码程序
OpenCV提供了一些基本的Webcam控制接口。用OpenCV C/C++或者Python,可以在任意平臺(tái)快速創(chuàng)建一個(gè)攝像頭預(yù)覽應(yīng)用。然而使用Java,情況就復(fù)雜的多,因?yàn)镺penCV Java并沒有提供一個(gè)類似于imshow的窗口顯示接口。想要?jiǎng)?chuàng)建一個(gè)帶界面的應(yīng)用,就需要通過OpenCV接口獲取數(shù)據(jù),并轉(zhuǎn)換成對(duì)應(yīng)的格式,然后通過Java的UI組件顯示出來。
OpenCV Java安裝
在OpenCV官網(wǎng)下載最新的Windows安裝包。
安裝后找到目錄opencv-4.3\opencv\build\java。
如果用Eclipse,可以直接導(dǎo)入工程。如果用Maven,需要先安裝到Maven的本地倉(cāng)庫(kù):
mvn install:install-file -Dfile=opencv-430.jar -DgroupId=org -DartifactId=opencv -Dversion=4.3.0 -Dpackaging=jar
然后在pom.xml文件里添加依賴:
org
opencv
4.3.0
還有一個(gè)問題就是dll文件怎么加載。如果找不到,會(huì)看到錯(cuò)誤信息:
Exception in thread "main" java.lang.UnsatisfiedLinkError: no opencv_java430 in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1867)
at java.lang.Runtime.loadLibrary0(Runtime.java:870)
at java.lang.System.loadLibrary(System.java:1122)
at com.java.barcode.App.main(App.java:65)
解決方法有幾種:
查看系統(tǒng)中的Java庫(kù)加載路徑。把dll文件放到對(duì)應(yīng)的路徑下即可: System.out.println(System.getProperty("java.library.path"));
使用全路徑加載: System.load("D:/opencv-4.3/opencv/build/java/x64/opencv_java430.dll");
啟動(dòng)程序的時(shí)候指定dll路徑: java -Djava.library.path= -cp target/opencv-dotcode-1.0-SNAPSHOT-jar-with-dependencies.jar com.java.barcode.App
攝像頭視頻窗口
在OpenCV Java的文檔中提供了一份基于JavaFX的示例代碼。
參考邏輯之后,也可以把代碼移植到Java Swing中。我這里用JLable來顯示視頻幀:
public void updateViewer(final BufferedImage image) {
if (!SwingUtilities.isEventDispatchThread()) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
mImage.setIcon(new ImageIcon(image));
}
});
return;
}
}
Runnable frameGrabber = new Runnable() {
@Override
public void run() {
Mat frame = grabFrame();
byte[] data = Utils.matToByteArray(frame);
if (!status.get()) {
status.set(true);
barcodeTimer.schedule(new BarcodeRunnable(frame, mBarcodeReader, callback, status), 0, TimeUnit.MILLISECONDS);
}
BufferedImage bufferedImage = Utils.byteToBufferedImage(data, frame.width(), frame.height(), frame.channels());
if (isRunning) updateViewer(bufferedImage);
}
};
this.timer = Executors.newSingleThreadScheduledExecutor();
this.timer.scheduleAtFixedRate(frameGrabber, 0, 33, TimeUnit.MILLISECONDS);
OpenCV接口運(yùn)行在獨(dú)立的線程中,需要通過SwingUtilities來更新UI。
示例:DotCode解碼
在pom.xml中添加Dynamsoft Barcode Reader SDK:
dbr
https://download.dynamsoft.com/maven/dbr/jar
com.dynamsoft
dbr
7.4.0
然后像OpenCV一樣創(chuàng)建一條線程來做條形碼解碼。
barcodeTimer = Executors.newSingleThreadScheduledExecutor();
Runnable中的代碼:
public void run() {
// TODO Auto-generated method stub
try {
TextResult[] results = reader.decodeBuffer(Utils.matToByteArray(frame), frame.width(), frame.height(), (int)frame.step1(), EnumImagePixelFormat.IPF_BGR_888, "");
if (results != null && results.length > 0) {
if (callback != null) {
callback.onResult(results, Utils.matToBufferedImage(frame));
}
}
else {
status.set(false);
}
} catch (BarcodeReaderException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
OpenCV獲取的數(shù)據(jù)類型是Mat。
條形碼解碼的時(shí)候要把Mat轉(zhuǎn)換成byte[]:
public static byte[] matToByteArray(Mat original)
{
int width = original.width(), height = original.height(), channels = original.channels();
byte[] sourcePixels = new byte[width * height * channels];
original.get(0, 0, sourcePixels);
return sourcePixels;
}
而在顯示畫面的時(shí)候,要把數(shù)據(jù)再轉(zhuǎn)成BufferedImage:
public static BufferedImage byteToBufferedImage(byte[] sourcePixels, int width, int height, int channels)
{
BufferedImage image = null;
if (channels > 1)
{
image = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
}
else
{
image = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
}
final byte[] targetPixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
System.arraycopy(sourcePixels, 0, targetPixels, 0, sourcePixels.length);
return image;
}
最后通過自定義的JLable來繪制條形碼的區(qū)域:
private ArrayList data = new ArrayList<>();
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (data.size() > 0) {
g2d.setColor(Color.RED);
for (Point[] points : data) {
for (int i = 0; i < points.length; ++i) {
if (i == 3) {
g2d.drawLine(points[i].x, points[i].y, points[0].x, points[0].y);
} else {
g2d.drawLine(points[i].x, points[i].y, points[i + 1].x, points[i + 1].y);
}
}
}
}
g2d.dispose();
}
public void appendPoints(Point[] points) {
data.add(points);
}
public void clearPoints() {
data.clear();
}
源碼
總結(jié)
以上是生活随笔為你收集整理的opencv java 摄像头_使用OpenCV Java创建Windows摄像头扫码程序的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java调用xdotool_【转】jav
- 下一篇: inheritance中文Java语言_