我正在尝试将Raspi的图片发送到我的电脑。Raspi上的程序使用Python运行。由于我的主要编程语言是Java,所以我想在Java应用程序中处理图像。作为模板,我采用了Raspicam文档的演示程序。
https://picamera.readthedocs.io/en/release-1.13/recipes1.html#capturing-对网络流
这是我的代码Python:
import socket
import struct
import time
import picamera
# Connect a client socket to my_server:8000 (change my_server to the
# hostname of your server)
client_socket = socket.socket()
client_socket.connect(('192.168.0.106', 8000))
# Make a file-like object out of the connection
connection = client_socket.makefile('wb')
try:
camera = picamera.PiCamera()
camera.resolution = (640, 480)
# Start a preview and let the camera warm up for 2 seconds
camera.start_preview()
time.sleep(2)
# Note the start time and construct a stream to hold image data
# temporarily (we could write it directly to connection but in this
# case we want to find out the size of each capture first to keep
# our protocol simple)
start = time.time()
stream = io.BytesIO()
while(True):
inputsignal= client_socket.recv(1)
if(inputsignal==b'x01'):
camera.capture(stream, 'jpeg')
size =stream.tell()
stream.seek(0)
print(size)
connection.write(struct.pack('<L', size))
connection.flush()
connection.write(stream.read())
connection.flush()
stream.seek(0)
stream.truncate(0)
print("Bild wurde gesendet")
continue
if(inputsignal==b'xFF'):
connection.write(struct.pack('<L', 0))
break
finally:
connection.close()
client_socket.close()
Java服务器
public static void getInetStream() {
try {
BufferedImage bim;
ServerSocket ssocket = new ServerSocket(8000);
System.out.println("Warte auf Verbindung...");
Socket s1 = ssocket.accept();
System.out.println("Verbindung hergestellt"+ s1.getInetAddress());
System.out.println("Warte auf Daten...");
OutputStream os = s1.getOutputStream();
InputStream stream = s1.getInputStream() ;
while(s1.isConnected()) {
//Force new Frame
os.write(1);
System.out.println("Neuer Frame wird geladen");
byte[] length = new byte[8];
stream.read(length);
int size= (length[3]<<24)&0xff000000|
(length[2]<<16)&0x00ff0000|
(length[1]<< 8)&0x0000ff00|
(length[0]<< 0)&0x000000ff;
System.out.println("Größe:"+size+" Bytes");
bim = ImageIO.read(stream);
System.out.println("Bild empfangen: "+bim.getHeight()+"/"+bim.getWidth());
label.setIcon(new ImageIcon(bim));
label.repaint();
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
现在的主要问题是,尽管所有的数据都被传输了,但图像会卡在输入流中。如果我写入另一个字节,则会传输新的字节以及完整的图像。也许ImageIO.read((就是问题所在。
以下是我从控制台输出的内容:Java
Warte auf Verbindung...
Verbindung hergestellt/192.168.0.143
Warte auf Daten...
Neuer Frame wird geladen
Größe:239021 Bytes
Python
pi@raspberrypi:~/Desktop $ /usr/bin/python3 /home/pi/Desktop/Camsocket.py
239021
Bild wurde gesendet
正如您所看到的,Python一定已经成功地发送了图像。
这里有一个适合我的解决方案。我不让ImageIO直接读取数据,而是先通过BufferedInputStream将其写入一个定义大小的数组中。我还不能说是否有更有效的方法。我达到了大约4fps,其中很大一部分用于数据传输。ImageIO+输出对帧的处理时间约为10-20ms。以下代码适用于PICamera文档中的演示:https://picamera.readthedocs.io/en/release-1.13/recipes1.html#capturing-对网络流只需复制Python代码并将其放在Raspi上即可。它应该很好用。有时尺寸读不正确。这将导致错误。
Java服务器:
public static void getInetStream() {
try {
long last_time = System.currentTimeMillis();
long current_time =0;
BufferedImage bim;
ServerSocket ssocket = new ServerSocket(8000);
System.out.println("Warte auf Verbindung...");
Socket s1 = ssocket.accept();
System.out.println("Verbindung hergestellt"+ s1.getInetAddress());
System.out.println("Warte auf Daten...");
OutputStream os = s1.getOutputStream();
InputStream stream = s1.getInputStream() ;
BufferedInputStream bis = new BufferedInputStream(stream);
byte[] length = new byte[4];
byte[] data;
while(s1.isConnected()) {
//Force new Frame
//os.write(1);
System.out.println("Neuer Frame wird geladen");
current_time=System.currentTimeMillis();
System.out.println("Delay: "+(current_time-last_time)+" ms");
last_time=System.currentTimeMillis();
stream.read(length);
int size= (length[3]<<24)&0xff000000|
(length[2]<<16)&0x00ff0000|
(length[1]<< 8)&0x0000ff00|
(length[0]<< 0)&0x000000ff;
if(size<=0) {
continue;
}
data=new byte[size];
System.out.println("Größe:"+size+" Bytes");
int data_ready;
int offset =0;
int readed =0;
while(true) {
data_ready = bis.available();
//System.out.println(data_ready);
if(data_ready>0) {
System.out.println("Offset: "+offset+" Bytes");
readed = bis.read(data,offset,size-offset);
offset=offset+readed;
System.out.println("Datenpaket empfangen:"+readed+" Bytes");
if(offset==size) {
break;
}
}
}
current_time=System.currentTimeMillis();
System.out.println("Dauer Datenempfang: "+(current_time-last_time)+" ms");
last_time=System.currentTimeMillis();
bim=ImageIO.read(new ByteArrayInputStream(data));
System.out.println("Daten empfangen");
System.out.println("Bild empfangen: "+bim.getHeight()+"/"+bim.getWidth());
label.setIcon(new ImageIcon(bim));
label.repaint();
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}