我很绝望,......我已经尝试并搜索了很多,但没有运气。请帮忙
一点背景: 使用 raspberry Pi 3,我开发了一个网络摄像头流媒体服务器,因为我不希望这些服务器可用。使用 raspistill 时,fps 非常低 (4fps),这就是为什么我研究用于流式传输网络摄像头的 v4l2 选项。为此,我将 mjpeg 视频输出到管道中。
从该管道读取时,会显示第一个 jpeg 图像,但连续读取会返回 null。
为了进一步研究这个问题,我制作了一个小型演示程序 - 结果相同。
这里是我使用的代码:
迭代 20 次从 bufferedinputstream 读取
private void standardRead()
{
BufferedInputStream bis = null;
try {
bis = new BufferedInputStream(new FileInputStream(new File(image_path)));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
System.out.println("Is mark supported? "+bis.markSupported());
try {
for(int i=0;i<20;i++)
{
readingImage(bis,i);
TimeUnit.MILLISECONDS.sleep(250);
}
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
读取方法(增强了一些System.out)
private void readingImage(BufferedInputStream bis,int iteration) throws IOException
{
System.out.println("Available bytes to read:"+bis.available());
System.out.println("Reading image"+iteration);
BufferedImage read = ImageIO.read(bis);
if(read!=null){
System.out.println(read.getRGB(25, 25)+" h:"+read.getHeight());System.out.println();
}else
{
System.out.println("image is null");
}
read = null;
}
我已经尝试过的: - 为每次迭代创建一个新的 BufferedInputStream - 关闭并创建一个新的 BufferedInputStream - 尝试使用标记和重置(没有运气) - 使用 read 而不是 ImageIO 从流中读取(显然以大约 20fps 的速度读取)
当我执行程序时,v4l2 通知帧已被消耗,因此管道正在被 java 程序清空/读取,以便可以将新帧输入其中。 只有第一张图片并且只有在程序第一次执行期间才会给我一个图片。该程序的第二次执行也为第一张图像提供了 null。
这里是一个示例输出:
Is mark supported? true
Available bytes to read:65536
Reading image0
image is null
Available bytes to read:73720
Reading image1
image is null
Available bytes to read:73712
Reading image2
image is null
Available bytes to read:73704
Reading image3
image is null
Available bytes to read:73696
Reading image4
image is null
Available bytes to read:73688
Reading image5
image is null
一个注释,如果有帮助的话。对于 ImageIO.read(InputStream) 函数,Java 文档说明了一些我无法理解的奇怪内容:
(...) The InputStream is wrapped in an ImageInputStream. If no registered ImageReader claims to be able to read the resulting stream, null is returned (...)
在此先感谢您的帮助和建议。
最佳答案
一个不眠之夜后,我得到了一些工作。
Eureka:我使用 v4l2 库将 1000 帧流式传输到 linux 管道中,并且可以读取所有 1000 帧。将每个文件保存到一个目录大约需要 103 秒,也就是 10fps。没有跳过任何一帧。
方法如下:
private void ReadImages(File path)
{
BufferedInputStream bis = null;
int index = 0;
ImageReader reader = null;
try {
bis = new BufferedInputStream(new FileInputStream(path));
ImageInputStream stream = ImageIO.createImageInputStream(bis);
while(bis.available()>0)
{
if(gotReader(stream))
{
reader = ImageIO.getImageReaders(stream).next();
reader.setInput(stream);
BufferedImage read = reader.read(index);
System.out.println("Image height"+read.getHeight() +" image width:"+read.getWidth()) ;
stream.flush();
index = 0;
}
}
} catch (IOException e) {
System.err.println(e.getMessage());
//e.printStackTrace();
}
}
提示:经常刷新流并重置索引。如果不刷新,不断增长的内存会显着破坏性能。
提示:标准 ImageIO 不读取 BGR3、RGB3、YU12、YUYV、YV12、YVYU,但读取 H264 和 MJPEG
提示:Reader 是用
测试的if(ImageIO.getImageReaders(stream).hasNext())
关于java - 从命名的 Linux 管道读取 BufferedInputStream 只能工作一次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42962476/