Я пытаюсь отправить видео через локальную сеть, которое записывается с помощью OpenCV в Python и отображается в приложении Android.
Моя оригинальная идея заключалась в том, чтобы:
Python side:
- получить изображение Mat из OpenCV
- конвертировать Mat в .png
- отправка байтов .png через SocketServer
Android:
- захват изображения с помощью BufferedInputStream
- , преобразование его в растровое изображение и отображение это в ImageView
Это работает, но только при определенных обстоятельствах. Когда первый байт в bufferedInputStream является первым байтом файла .png. Так как первые 2 в основном не повреждены, но остальные из них. Я понимаю, что BufferedInputStream пытается прочитать 400 000 байтов, и это также вызывает повреждение изображений. Но это означает, что мне нужно знать точный размер входящего изображения, и BufferedInputStream не всегда загружает все 400 000 (иногда только 50 000). Так что это кажется мне слишком сложным.
И как только сервер python начинает выводить данные через сокет sh, возникает беспорядок и изображения повреждаются.
Вот Python код:
import socket
import cv2
HOST = '192.168.1.105'
PORT = 6969
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
# Connect to webcam
stream = cv2.VideoCapture(0)
while True:
# grab the Mat image
_, img = stream.read()
_, png_img = cv2.imencode('.png', img)
png_img = png_img.tobytes()
s.sendall(png_img)
Вот код Android:
import androidx.appcompat.app.AppCompatActivity;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.widget.ImageView;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Thread server_thread = new Thread(new ServerThread());
server_thread.start();
}
class ServerThread implements Runnable {
Socket socket;
ServerSocket serverSocket;
Handler handler = new Handler();
InputStream inputStream;
BufferedInputStream bufferedInputStream;
// set to random, but my images are always smaller than this
int my_buffer_size = 400000;
int read_bytes;
byte[] received_bytes;
@Override
public void run() {
try {
serverSocket = new ServerSocket(6969);
System.out.println("Server Socket is on port 6969");
// Wait for someone to connect
socket = serverSocket.accept();
inputStream = socket.getInputStream();
bufferedInputStream = new BufferedInputStream(inputStream);
while (true) {
received_bytes = new byte[my_buffer_size];
read_bytes = bufferedInputStream.read(received_bytes);
System.out.println("Read bytes: " + read_bytes);
handler.post(new Runnable() {
@Override
public void run() {
ImageView imgView = (ImageView) findViewById(R.id.image);
imgView.setImageBitmap(BitmapFactory.decodeByteArray(received_bytes, 0, my_buffer_size));
}
});
}
} catch(IOException e){
e.printStackTrace();
System.out.println("ERROR: Run failed.");
}
}
}
}
Я не уверен, если этот метод "отправить .png и отобразить его в ImageView" метод правильный путь к go. Я хотел бы услышать от вас, ребята, каков подход к проблеме, подобной этой? И если это должно сработать, как я могу улучшить его, чтобы получить живое видео без поврежденных изображений?