System.err.println()是什么?什么时候要用到它

本文介绍了Java中System.err的作用及其特点,System.err主要用于输出运行时异常和错误信息,其输出的文字在某些IDE如Eclipse中会以红色显示。文章还强调了System.err的输出不能被重定向。
err是运行期异常和错误反馈的输出流的方向。 

System.err.println只能在屏幕上实现打印,即使你重定向了也一样。 

要说 最直接的区别的话: 

就是 如果 你使用err打印出的 字符串,再eclipse的console会显示成红色的哦。

转自:http://zhidao.baidu.com/link?url=XASyo25NZbSY70B_E9zV6-WoNbfxE9wmK_om8cbizxRK3BKH-oBP0XrI4VlDb-VI7k8YQvxfxSFAFTqRC1AIuq

package com.dnf.main; import java.awt.image.BufferedImage; import java.awt.image.DataBufferByte; import java.nio.ByteBuffer; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import javax.swing.SwingUtilities; import org.opencv.core.Mat; import org.opencv.imgproc.Imgproc; import org.opencv.videoio.VideoCapture; import org.opencv.videoio.Videoio; import org.opencv.videoio.VideoWriter; import javafx.application.Platform; import javafx.embed.swing.JFXPanel; import javafx.scene.Scene; import javafx.scene.image.ImageView; import javafx.scene.image.PixelFormat; import javafx.scene.image.WritableImage; import javafx.scene.layout.Background; import javafx.scene.layout.BackgroundFill; import javafx.scene.layout.CornerRadii; import javafx.scene.layout.StackPane; import javafx.scene.paint.Color; public class MS2130FXCapture { // 核心资源 private static ImageView imageView; private static VideoCapture videoCapture; // 状态控制 private static final AtomicBoolean isRunning = new AtomicBoolean(false); private static final AtomicBoolean isFXInitialized = new AtomicBoolean(false); // 线程管理 private static Thread captureThread; private static ExecutorService frameProcessingPool; // 资源池控制 private static final int MAT_POOL_SIZE = 4; private static final BlockingQueue<Mat> matPool = new ArrayBlockingQueue<>(MAT_POOL_SIZE); // 显示资源 private static final AtomicReference<BufferedImage> bufImgRef = new AtomicReference<>(); private static final AtomicReference<WritableImage> fxImgRef = new AtomicReference<>(); private static volatile Mat displayMat; // 帧率控制 private static final int TARGET_FPS = 30; private static final long FRAME_INTERVAL_MS = 1000 / TARGET_FPS; private static long lastFrameTime = System.currentTimeMillis(); // 设备参数 private static int deviceWidth = 1920; private static int deviceHeight = 1080; /** * 启动视频采集 */ public static void startCapture(JFXPanel fxPanel) { System.out.println("[自动采集] 开始初始化采集"); // 确保停止之前的采集 stopCapture(); // 重置状态 isRunning.set(true); System.out.println("[状态] isRunning 设置为 true"); int deviceIndex = findValidDeviceIndex(); if (deviceIndex == -1) { System.err.println("[错误] 未找到MS2130设备"); return; } // 初始化Mat池并预热 initMatPool(); // 初始化JavaFX环境 if (!isFXInitialized.get()) { System.out.println("[初始化] 首次初始化JavaFX"); SwingUtilities.invokeLater(() -> { Platform.runLater(() -> { System.out.println("[JavaFX] 在JavaFX线程中初始化"); initFXCapture(fxPanel, deviceIndex); isFXInitialized.set(true); }); }); } else { System.out.println("[初始化] JavaFX已初始化,直接启动采集"); Platform.runLater(() -> initFXCapture(fxPanel, deviceIndex)); } // 初始化线程池 frameProcessingPool = Executors.newFixedThreadPool(2); System.out.println("[线程池] 帧处理线程池已创建"); } /** * 初始化Mat对象池 */ private static void initMatPool() { synchronized (matPool) { matPool.clear(); for (int i = 0; i < MAT_POOL_SIZE; i++) { matPool.offer(new Mat()); } System.out.println("[资源池] Mat对象池已初始化,大小: " + MAT_POOL_SIZE); } } /** * 初始化JavaFX UI组件 */ private static void initFXCapture(JFXPanel fxPanel, int deviceIndex) { System.out.println("[UI] 初始化JavaFX UI组件"); imageView = new ImageView(); imageView.setPreserveRatio(true); imageView.setSmooth(true); imageView.setCache(false); StackPane root = new StackPane(imageView); root.setBackground(new Background( new BackgroundFill(Color.BLACK, CornerRadii.EMPTY, javafx.geometry.Insets.EMPTY) )); fxPanel.setScene(new Scene(root)); System.out.println("[UI] JavaFX场景已设置"); openDeviceAndStartCapture(deviceIndex); } /** * 枚举有效设备 */ private static int findValidDeviceIndex() { System.out.println("[设备检测] 开始检测可用设备..."); for (int i = 0; i < 4; i++) { VideoCapture testCapture = null; try { System.out.println("[设备检测] 尝试索引: " + i); // 尝试使用DSHOW驱动 testCapture = new VideoCapture(i, Videoio.CAP_DSHOW); if (!testCapture.isOpened()) { System.out.println("[设备检测] DSHOW驱动打开失败,尝试MSMF"); testCapture.release(); testCapture = new VideoCapture(i, Videoio.CAP_MSMF); } if (!testCapture.isOpened()) { System.out.println("[设备检测] 设备 " + i + " 未打开"); continue; } Mat testFrame = new Mat(); if (testCapture.read(testFrame) && !testFrame.empty()) { // deviceWidth = (int) testCapture.get(Videoio.CAP_PROP_FRAME_WIDTH); // deviceHeight = (int) testCapture.get(Videoio.CAP_PROP_FRAME_HEIGHT); // System.out.printf("[设备检测] 发现设备 %d: %dx%d%n", i, deviceWidth, deviceHeight); testFrame.release(); testCapture.release(); return i; } else { System.out.println("[设备检测] 设备 " + i + " 读取帧失败"); } testFrame.release(); } catch (Exception e) { System.err.println("设备检测错误: " + e.getMessage()); } finally { if (testCapture != null && testCapture.isOpened()) { testCapture.release(); } } } System.out.println("[设备检测] 未找到可用设备"); return -1; } /** * 打开设备并配置 */ private static void openDeviceAndStartCapture(int deviceIndex) { System.out.println("[设备] 尝试打开设备: " + deviceIndex); // 尝试多种驱动 videoCapture = new VideoCapture(deviceIndex, Videoio.CAP_DSHOW); if (!videoCapture.isOpened()) { System.out.println("[设备] DSHOW驱动打开失败,尝试MSMF"); videoCapture.open(deviceIndex, Videoio.CAP_MSMF); } if (!videoCapture.isOpened()) { System.err.println("[错误] 无法打开设备"); return; } // 设置设备参数 videoCapture.set(Videoio.CAP_PROP_FRAME_WIDTH, deviceWidth); videoCapture.set(Videoio.CAP_PROP_FRAME_HEIGHT, deviceHeight); videoCapture.set(Videoio.CAP_PROP_FOURCC, VideoWriter.fourcc('M', 'J', 'P', 'G')); videoCapture.set(Videoio.CAP_PROP_BUFFERSIZE, 2); videoCapture.set(Videoio.CAP_PROP_FPS, TARGET_FPS); System.out.printf("[设备] 设备已打开: %dx%d@%dFPS%n", deviceWidth, deviceHeight, TARGET_FPS); // 创建显示用的Mat displayMat = new Mat(deviceHeight, deviceWidth, org.opencv.core.CvType.CV_8UC3); System.out.println("[资源] 显示Mat已创建"); // 启动采集线程 captureThread = new Thread(() -> captureLoop()); captureThread.setName("VideoCapture-Thread"); captureThread.setDaemon(true); captureThread.setPriority(Thread.MAX_PRIORITY - 1); // 适度优先级 captureThread.start(); System.out.println("[线程] 采集线程已启动"); } /** * 优化的采集循环 */ private static void captureLoop() { System.out.println("[采集线程] 开始运行"); System.out.println("[状态] isRunning = " + isRunning.get()); long frameCount = 0; final long startTime = System.currentTimeMillis(); int consecutiveFailures = 0; while (isRunning.get()) { try { // 帧率控制 long currentTime = System.currentTimeMillis(); long elapsed = currentTime - lastFrameTime; if (elapsed < FRAME_INTERVAL_MS) { Thread.sleep(1); continue; } // 获取空闲Mat Mat frameMat = matPool.poll(); if (frameMat == null) { System.out.println("[资源] Mat池为空,创建新Mat"); frameMat = new Mat(); } // 读取帧 boolean readSuccess = videoCapture.read(frameMat); if (!readSuccess || frameMat.empty()) { System.out.println("[警告] 读取帧失败: " + (frameMat.empty() ? "空帧" : "读取失败")); consecutiveFailures++; if (consecutiveFailures > 10) { System.err.println("[错误] 连续10次读取帧失败,停止采集"); break; } // 归还Mat并等待 if (frameMat != null && frameMat.cols() > 0) { matPool.offer(frameMat); } Thread.sleep(10); continue; } consecutiveFailures = 0; // 重置失败计数 // 更新计时器 lastFrameTime = currentTime; frameCount++; // 提交处理任务 final Mat finalFrameMat = frameMat; frameProcessingPool.execute(() -> processFrame(finalFrameMat)); // 性能日志(每秒输出一次) if (currentTime - startTime > 1000) { double fps = frameCount / ((currentTime - startTime) / 1000.0); System.out.printf("[性能] FPS: %.1f%n", fps); frameCount = 0; } } catch (InterruptedException e) { System.out.println("[线程] 采集线程被中断"); Thread.currentThread().interrupt(); break; } catch (Exception e) { System.err.println("采集线程错误: " + e.getMessage()); e.printStackTrace(); } } System.out.println("[采集线程] 安全退出"); } /** * 优化的帧处理 */ private static void processFrame(Mat frameMat) { try { // 转换颜色空间 if (displayMat == null) { System.out.println("[警告] displayMat为空,创建新的displayMat"); displayMat = new Mat(frameMat.rows(), frameMat.cols(), frameMat.type()); } Imgproc.cvtColor(frameMat, displayMat, Imgproc.COLOR_BGR2RGB); // 获取帧参数 final int width = displayMat.cols(); final int height = displayMat.rows(); // 初始化或复用BufferedImage BufferedImage bufImg = bufImgRef.get(); if (bufImg == null || bufImg.getWidth() != width || bufImg.getHeight() != height) { System.out.printf("[资源] 创建新BufferedImage: %dx%d%n", width, height); bufImg = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR); bufImgRef.set(bufImg); } // 直接像素复制 byte[] imgPixels = ((DataBufferByte) bufImg.getRaster().getDataBuffer()).getData(); displayMat.get(0, 0, imgPixels); // JavaFX线程安全更新 Platform.runLater(() -> { if (!isRunning.get() || imageView == null) { System.out.println("[更新] 跳过UI更新: isRunning=" + isRunning.get() + ", imageView=" + (imageView != null)); return; } // 获取或创建JavaFX图像 WritableImage fxImg = fxImgRef.get(); if (fxImg == null || (int)fxImg.getWidth() != width || (int)fxImg.getHeight() != height) { System.out.printf("[资源] 创建新WritableImage: %dx%d%n", width, height); fxImg = new WritableImage(width, height); fxImgRef.set(fxImg); } // 直接写入像素数据 PixelFormat<ByteBuffer> pixelFormat = PixelFormat.getByteRgbInstance(); fxImg.getPixelWriter().setPixels( 0, 0, width, height, pixelFormat, imgPixels, 0, width * 3 ); imageView.setImage(fxImg); }); } catch (Exception e) { System.err.println("帧处理错误: " + e.getMessage()); e.printStackTrace(); } finally { // 释放资源 if (frameMat != null) { frameMat.release(); } // 补充新的Mat到池中 if (matPool.remainingCapacity() > 0) { matPool.offer(new Mat()); } } } /** * 全局资源清理 */ private static synchronized void cleanupResources() { System.out.println("[资源清理] 开始清理资源"); isRunning.set(false); System.out.println("[状态] isRunning 设置为 false"); // 关闭视频捕获 if (videoCapture != null) { if (videoCapture.isOpened()) { videoCapture.release(); System.out.println("[资源] VideoCapture已释放"); } videoCapture = null; } // 释放Mat对象池 synchronized (matPool) { Mat mat; while ((mat = matPool.poll()) != null) { if (!mat.empty()) { mat.release(); } } System.out.println("[资源] Mat对象池已清空"); } // 释放显示Mat if (displayMat != null) { displayMat.release(); displayMat = null; System.out.println("[资源] displayMat已释放"); } // 关闭线程池 if (frameProcessingPool != null) { try { frameProcessingPool.shutdown(); if (!frameProcessingPool.awaitTermination(500, TimeUnit.MILLISECONDS)) { frameProcessingPool.shutdownNow(); } System.out.println("[线程池] 帧处理线程池已关闭"); } catch (InterruptedException e) { frameProcessingPool.shutdownNow(); Thread.currentThread().interrupt(); } } // 清空图像引用 Platform.runLater(() -> { if (imageView != null) { imageView.setImage(null); } }); bufImgRef.set(null); fxImgRef.set(null); System.out.println("[资源清理] 资源清理完成"); } /** * 停止采集 */ public static synchronized void stopCapture() { if (!isRunning.get()) { System.out.println("[停止采集] 采集未运行,无需停止"); return; } System.out.println("[停止采集] 请求停止..."); isRunning.set(false); if (captureThread != null && captureThread.isAlive()) { captureThread.interrupt(); try { captureThread.join(1000); System.out.println("[线程] 采集线程已停止"); } catch (InterruptedException e) { System.out.println("[线程] 停止采集线程时被中断"); Thread.currentThread().interrupt(); } } cleanupResources(); System.out.println("[停止采集] 资源已释放"); } } 1.设备的分辨率是1920*1080这个采集的数据要固定下来,之后我需要对这种分辨率的图像进行处理; 2.采集画面的显示可以不用1920*1080的显示,可以保持画面比例16:9的比例低一点的像素去显示默认按照800*450的比例去显示吧;应该怎么修改
10-20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值