swing - 如何在 JavaFX 应用程序中显示 OpenCV 网络摄像头捕获帧

标签 swing kotlin javafx qr-code javacv

我正在使用 创建桌面应用程序JavaFX ,它允许您从网络摄像头扫描二维码。
我决定选择 JavaCV 来处理网络摄像头捕获。但是,问题在于 CanvasFrame类创建一个 Swing JFrame .我的主要目标是找到将它与 JavaFX 组件集成的最佳方法。
我的问题是是否可以创建 CanvasFrameJPanel (或其他 Swing/JavaFx 组件),不在 JFrame 中.在这个选项中,我将包装 JPanel进入 SwingNode - 它解决了我的集成问题。
在我的情况下,我还要求其他解决 JavaFX 与 JavaCV 集成问题的建议。
也许有一种直接的方法可以将相机屏幕嵌入到 JavaFx 组件中。
我在下面粘贴测试代码。我的代码是用kotlin写的,但是不影响问题:

import com.google.zxing.*
import com.google.zxing.client.j2se.BufferedImageLuminanceSource
import com.google.zxing.common.HybridBinarizer
import org.bytedeco.javacv.*
import java.awt.image.BufferedImage
import java.util.*
import java.util.concurrent.Executors

class Test {
    companion object {
        @JvmStatic
        fun main(args: Array<String>) {
            Executors.newSingleThreadExecutor().execute { testWebcam() }
        }

        private fun testWebcam() {
            val grabber: OpenCVFrameGrabber = OpenCVFrameGrabber(0);
            val canvasFrame: CanvasFrame = CanvasFrame("Cam")
            grabber.start()

            while (canvasFrame.isVisible) {
                val frame: Frame = grabber.grabFrame() ?: break
                canvasFrame.showImage(frame)
                decodeQrCode(grabber)
            }
        }

        private fun decodeQrCode(grabber: OpenCVFrameGrabber) {
            val java2DFrameConverter: Java2DFrameConverter = Java2DFrameConverter()

            val frame: Frame = grabber.grabFrame()
            val image = java2DFrameConverter.getBufferedImage(frame)

            val decodedQr = parseQr(image)
            println(decodedQr)
        }

        private fun parseQr(image: BufferedImage): String? {

            val reader: MultiFormatReader = MultiFormatReader()
            val binaryBitmap: BinaryBitmap =
                BinaryBitmap(HybridBinarizer(BufferedImageLuminanceSource(image)))

            val hints: Hashtable<DecodeHintType, Any> = Hashtable()
            hints[DecodeHintType.CHARACTER_SET] = "UTF-8"
            hints[DecodeHintType.POSSIBLE_FORMATS] = listOf(BarcodeFormat.QR_CODE)

            return try {
                reader.decode(binaryBitmap, hints).text
            } catch (e: NotFoundException) {
                null;
            }

        }
    }
}

最佳答案

https://github.com/rladstaetter/javacv-webcam有一个项目有使用 javacv 的示例使用 Swing、JavaFX 以及在 OpenCV 和 JavaFX 的 PixelBuffer 之间使用共享内存缓冲区的更新方法。
您可以使用由共享 ByteBuffer 支持的 JavaFX 的 ImageView,而不是使用 CanvasFrame。伪代码是:

import java.nio.ByteBuffer

import javafx.scene.image._
import org.bytedeco.javacv.Frame
import org.bytedeco.opencv.global.opencv_imgproc._
import org.bytedeco.opencv.opencv_core.Mat

val videoView: ImageView = ImageView()
val grabber: OpenCVFrameGrabber = OpenCVFrameGrabber(0)
grabber.start()

// Fire off a thread to grab frames while the camera is active
// Each frame will ber passed to the updateView method below
// ... timer/thread omitted for brevity

val javaCVMat = Mat()

/** create buffer only once saves much time! */
val buffer: ByteBuffer = javaCVMat.createBuffer()

val formatByte: WritablePixelFormat<ByteBuffer> = PixelFormat.getByteBgraPreInstance()

fun updateView(frame: Frame): Unit = {
  val w = frame.imageWidth()
  val h = frame.imageHeight()

  val mat = javaCVConv.convert(frame)
  cvtColor(mat, javaCVMat, COLOR_BGR2BGRA)

  val pb = PixelBuffer(w, h, buffer, formatByte)
  val wi = WritableImage(pb)
  videoView.setImage(wi)
}

关于swing - 如何在 JavaFX 应用程序中显示 OpenCV 网络摄像头捕获帧,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62993437/

相关文章:

java - 用 Java 绘制 Hello World 最快的方法是什么

java - 从 JTable 的文本文件中解析日期

java - 如何在 Gradle 多项目构建中配置每个 Kotlin 项目?

java - 更改时更改显示值

java - JAR部署时文件目录错误

java - 更改 JFreeChart GanttChart 上的范围轴 - 非工作时间的 SegmentedTimeline

java - 如何绘制一条正确指向屏幕角落图像的线

validation - 在 Kotlin 中,根据属性的类型限制注解目标

android - 如何在收到服务器响应后停止进度条

java - 在 JavaFX 中显示和隐藏主舞台