低于17毫秒截取屏幕图像:终极解决方案
2024-03-20 21:05:18
以低于 17 毫秒的速度截取屏幕图像:终极指南
作为一名经验丰富的程序员,我一直在寻求以低于 17 毫秒的速度截取屏幕图像的方法。在本文中,我将分享我遇到的挑战、探索过的解决方案以及最终找到的突破性方法。
问题陈述:
对于许多图像处理和计算机视觉任务,至关重要的是以高帧率捕获屏幕图像。然而,使用传统的 Kotlin 解决方案,例如 Robot().createScreenCapture(),我发现无法达到所需的 17 毫秒速度。
尝试过的解决方案:
为了解决这个问题,我尝试了各种方法,包括:
- 多线程 Robot: 使用多个 Robot 线程来并行化屏幕截图过程。
- FFMpegGrabber: 使用开源 FFMpeg 库来捕获屏幕视频并从中提取图像。
- 程序的多个实例: 启动程序的多个实例,每个实例负责捕获特定区域的屏幕。
突破性方法:
尽管这些解决方案有所改善,但它们仍然无法达到 17 毫秒的速度目标。最终,我转向了特定于操作系统的低级库,如:
- Windows: DirectX (DXGI) 或 Windows Graphics Device Interface (GDI)
- Linux: Xlib
- macOS: Core Graphics (Core Graphics)
通过使用 Java Native Interface (JNI),我能够调用这些低级库并大幅提升屏幕截图性能。
实现:
以下是如何使用 DXGI 在 Windows 中截取屏幕图像的示例代码:
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinNT.RECT;
import com.sun.jna.ptr.IntByReference;
public class ScreenCapture {
private static final User32 USER32 = User32.INSTANCE;
private static final Kernel32 KERNEL32 = Kernel32.INSTANCE;
public static BufferedImage captureScreen() {
HWND hwnd = USER32.GetDesktopWindow();
RECT rect = new RECT();
USER32.GetWindowRect(hwnd, rect);
int width = rect.right - rect.left;
int height = rect.bottom - rect.top;
Pointer hdc = USER32.GetWindowDC(hwnd);
IntByReference hdcMem = new IntByReference();
IntByReference hbmp = new IntByReference();
hdcMem.setValue(GDI32.CreateCompatibleDC(hdc));
hbmp.setValue(GDI32.CreateCompatibleBitmap(hdc, width, height));
GDI32.SelectObject(hdcMem, hbmp);
GDI32.BitBlt(hdcMem, 0, 0, width, height, hdc, 0, 0, GDI32.SRCCOPY);
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = image.createGraphics();
g2d.drawImage(GDI32.GetBitmapBits(hbmp, image.getWidth() * image.getHeight() * 3), 0, 0, null);
GDI32.DeleteObject(hbmp);
GDI32.DeleteObject(hdcMem);
USER32.ReleaseDC(hwnd, hdc);
return image;
}
}
优化:
为了进一步提高性能,可以考虑以下优化技术:
- 并行处理: 将屏幕图像的捕获过程分成多个并行任务。
- 缓存: 缓存屏幕截图以避免重复捕获。
- 帧跳过: 只捕获必要帧,而不是每个帧。
结论:
通过使用特定于操作系统的低级库并实施优化技术,可以将屏幕截图性能提升至低于 17 毫秒的速度。这对于图像处理、计算机视觉和许多其他需要高帧率捕获的应用程序非常有价值。
常见问题解答:
-
为什么我无法使用 Robot().createScreenCapture() 达到 17 毫秒的速度?
Robot 类使用 Java AWT,它具有较高的开销。低级库绕过了这一开销。
-
使用 JNI 有哪些风险?
不当使用 JNI 可能会导致内存泄漏和程序崩溃。确保仔细清理资源。
-
如何优化屏幕截图性能?
并行化捕获过程,缓存屏幕截图,并仅捕获必要的帧。
-
我可以在哪些平台上使用低级库?
本指南介绍了 Windows、Linux 和 macOS 的低级库。
-
我可以在哪里找到更多信息?
有关特定于操作系统的低级库的更多信息,请参阅 Microsoft、X.Org Foundation 和 Apple 的文档。