问题
What basically i want to do is implement live video streaming in java. i.e grab video infront of webcam of one computer and send that video to other computer in real time
This is my server side code where i grab images in a loop using opencv libraries and and then save it to a file. I then open it using a Filestream and send it to other network and below is my client side code
Error: I get only one image on client side i.e the first captured image from webcam
What is the workaround to get all images i.e as a video on client side
I have imported all the necessary packages
public class filesen{
static IplImage bimg;
public static void main(String ar[])throws Exception{
Socket clientSocket=new Socket("localhost",1234);
CanvasFrame canvas = new CanvasFrame("sending");
//int i=1;
FrameGrabber grabber = new OpenCVFrameGrabber("");
try {
grabber.start();
IplImage img;
while (true) {
OutputStream out=clientSocket.getOutputStream();
img = grabber.grab();
if (img != null) {
opencv_highgui.cvSaveImage("a.jpg", img);
FileInputStream fis=new FileInputStream("a.jpg");
System.out.println(fis);
int x=0;
while(true){
x=fis.read();
if(x==-1)break;
out.write(x);
}
bimg = opencv_highgui.cvLoadImage("a.jpg");
canvas.showImage(bimg);
// out.close();
//canvas.showImage(img);
i++;
System.out.println(i);
}
}
}
catch (Exception e) {
}
}
}
This is my client side code
public class filere extends Applet {
//static IplImage bimg;
public static void main(String ar[]) throws Exception{
CanvasFrame canvas = new CanvasFrame("Webcam");
ServerSocket ss=new ServerSocket(1234);
while(true){
Socket clientSocket=ss.accept();
InputStream in=clientSocket.getInputStream();
//OutputStream out=clientSocket.getOutputStream();
FileOutputStream fos=new FileOutputStream("b.jpg");
int x=0;
while(true){
x=in.read();
if(x==-1)break;
fos.write(x);
}
bimg = opencv_highgui.cvLoadImage("b.jpg");
canvas.showImage(bimg);
}
}
}
回答1:
Think of it like this...
You have a producer, which generates images, you have a consumer, which wants to get those images.
The consumer asks the producer for the next image, when the producer is ready, it sends the next image and the consumer, well, consumes it in what ever manner it wants...
Normally, the consumer waits for the producer to produce something and then processes it, I took a slightly different direction, allowing the consumer to "request" the next available image. This allows the producer to continue on it's merry little way without being bogged down by sending EVERYTHING it can...
Why you might ask, because generating the frames may be quicker than sending them over the network, this way you could generate a frame dropping algorithm, filling a queue with images and having the queue manage the number of frames it's willing to buffer. The "producer" would then pull frames of the queue at the request of the consumer and send them...
This is a proof of concept only, it does not deal with multiple connections or connection recovery or a bunch of other things that you will need to deal with
This example has the producer (the server), sending images file from a directory on the server. It will keep sending images, at the request of the client/consumer until there are no more images left, at which time it will send the "NoMoreImages" response...
The consumer will request the next image from the server, write it to disk and continue until it receives the "NoMoreImages" response at which time it will exit...
Consumer
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
public class Consumer {
public static void main(String[] args) {
System.out.println("Connecting to producer");
try (Socket socket = new Socket("localhost", 1234)) {
try (InputStream is = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
OutputStream os = socket.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os))) {
boolean moreImages = true;
int imageCount = 0;
do {
System.out.println("Requesting next image " + imageCount);
writer.write("NextImage");
writer.newLine();
writer.flush();
String response = reader.readLine();
System.out.println("Got response " + response);
if (response.startsWith("NextImage;")) {
String type = response.split(";")[1];
String lengthValue = response.split(";")[2];
long bytesToBeConsumed = Long.parseLong(lengthValue);
try (FileOutputStream fos = new FileOutputStream(new File("Image" + imageCount + "." + type))) {
long bytesThatHaveBeenConsumed = 0;
int bytesThatWereRead = 0;
byte[] buffer = new byte[2048];
System.out.println("Reading image of type " + type + " of byte length " + bytesToBeConsumed);
while (bytesThatHaveBeenConsumed != bytesToBeConsumed && (bytesThatWereRead = is.read(buffer)) != -1) {
bytesThatHaveBeenConsumed += bytesThatWereRead;
fos.write(buffer, 0, bytesThatWereRead);
}
System.out.println("Finished reading image " + imageCount + " with " + bytesThatHaveBeenConsumed + " bytes consumed");
}
imageCount++;
} else if (response.startsWith("NoMoreImages")) {
moreImages = false;
System.out.println("No more images...");
writer.write("Bye");
writer.newLine();
writer.flush();
}
} while (moreImages);
}
} catch (IOException exp) {
exp.printStackTrace();
}
System.out.println("Consumer has left the building...");
}
}
Producer
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class Producer {
public static void main(String[] args) {
try (ServerSocket serverSocket = new ServerSocket(1234)) {
System.out.println("Waiting for connection from consumer...");
try (Socket socket = serverSocket.accept()) {
System.out.println("Listing files...");
File[] images = new File("/some/directory/full/of/images").listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
String name = pathname.getName().toLowerCase();
return name.endsWith(".gif")
|| name.endsWith(".jpeg")
|| name.endsWith(".jpg")
|| name.endsWith(".png");
}
});
System.out.println("Have " + images.length);
int imageIndex = 0;
try (InputStream is = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
OutputStream os = socket.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os))) {
boolean moreRequets = true;
do {
System.out.println("Waiting for consumer request");
String request = reader.readLine();
if ("NextImage".equals(request)) {
System.out.println("Get next image " + imageIndex);
if (images != null && imageIndex < images.length) {
File imageFile = images[imageIndex];
imageIndex++;
long length = imageFile.length();
String type = imageFile.getName();
type = type.substring(type.lastIndexOf(".") + 1).toLowerCase();
String response = new StringBuilder(128).
append("NextImage;").
append(type).
append(";").
append(length).toString();
System.out.println("Sending response to consumer " + response);
writer.write(response);
writer.newLine();
writer.flush();
System.out.println("Sending file...");
try (FileInputStream fis = new FileInputStream(imageFile)) {
byte[] buffer = new byte[2048];
int bytesRead = -1;
while ((bytesRead = fis.read(buffer)) != -1) {
os.write(buffer, 0, bytesRead);
}
}
System.out.println("File sent...");
} else {
System.out.println("No more images...");
writer.write("NoMoreImages");
writer.newLine();
writer.flush();
}
} else if ("Bye".equals(request)) {
moreRequets = false;
System.out.println("Consumer has left the building...");
}
} while (moreRequets);
}
}
} catch (IOException exp) {
exp.printStackTrace();
}
System.out.println("Producer has left the building");
}
}
I can't stress enough, that this is a proof of concept only, you really should consider having a separate thread to manage the incoming connections to the server, so each client can be handled independently.
You should not be mixing your socket management with you GUI management, these should be managed in separate threads and GUI updates should be maintained within the context of the main GUI thread.
回答2:
Finally i got to transfer number of images from server to client.
Mistake i have done is accesing the image file before it is even created. so i tried to access the image files after waiting for 200ms using sleep.
The whole implementation can be found here(on github) in three different classes
'webcam.java' 'Image_Server.java' 'Client_camera_Image.java'
ofcourse there is some delay(5-10ms) in transfer of video and it would be great if anyone could improve the code.
The current code eats too much of RAM. suggestions needed there too.
I have used Opencv and javacv libraries for image grabbing.
来源:https://stackoverflow.com/questions/26495165/i-get-only-one-image-while-transferring-in-a-loop-over-a-socket-in-java