我正在使用 创建桌面应用程序JavaFX ,它允许您从网络摄像头扫描二维码。
我决定选择 JavaCV 来处理网络摄像头捕获。但是,问题在于 CanvasFrame
类创建一个 Swing JFrame
.我的主要目标是找到将它与 JavaFX 组件集成的最佳方法。
我的问题是是否可以创建 CanvasFrame
在 JPanel
(或其他 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/