借助JavaCV实现android手机查看PC摄像头实时视频

查看PC实时摄像头视频,其实就是以大于24次/秒的速度,控制PC摄像头进行拍照,并把每一张拍得的图片发送到android手机端,在手机上展示这些图片,得到实时的视频。

主要解决两个问题一时调用PC摄像头拍摄图片,二是在PC和android之间传输图片。

利用JavaCV(简介见本文末尾)调用PC摄像头很简单

OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(0);
grabber.start();
//调用grab()方法就能得到IplImage类的一个对象,进行进一步处理就能得到图片

传输图片涉及图片数据和字节流之间的转化

PC端将图片转化为字节流

while ((image = grabber.grab()) != null && writeImageSocket.isConnected()) {
					ByteArrayOutputStream baos = new ByteArrayOutputStream();
					ImageIO.write(image.getBufferedImage(), "jpg", baos );
					baos.flush();
					byte[] imageInByte = baos.toByteArray(); 
					baos.close();
					
					dos.writeInt(imageInByte.length);
					dos.write(imageInByte,0,imageInByte.length);
					dos.flush();

				}
Android读取字节流转化为图片
while (true) {
					int size = dataInput.readInt();
					Log.e("size in client", Integer.toString(size));
					byte[] data = new byte[size];
					int len = 0;
					while (len < size) {
						len += dataInput.read(data, len, size - len);
					}
					ByteArrayOutputStream outPut = new ByteArrayOutputStream();
					bitmap = BitmapFactory.decodeByteArray(data, 0,
							data.length);
					bitmap.compress(CompressFormat.PNG, 100, outPut);
					Message message = new Message();
					message.what = 1;
					mHandler.sendMessage(message);
				}
具体代码

PC端服务程序的实现CameraSever.java

package com.giantpoplar.cameraserver;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

import javax.imageio.ImageIO;

import com.googlecode.javacv.FrameGrabber.Exception;
import com.googlecode.javacv.cpp.opencv_core.IplImage;
import com.googlecode.javacv.OpenCVFrameGrabber;

public class CameraSever {

	

	public  CameraSever() {
	
		ServerSocket serversocket = null;
		Executor executor = null;
		OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(0);
		try {
			serversocket = new ServerSocket(8888);	
			executor = Executors.newCachedThreadPool();
			grabber.start();						
			while (!serversocket.isClosed()) {
				Socket acceptedSocket = serversocket.accept();
				executor.execute(new SendImageThread(acceptedSocket, grabber));
			}
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (serversocket != null) {
				try {
					serversocket.close();
					grabber.stop();
				} catch (IOException e) {
					e.printStackTrace();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}

		}
	}

	private class SendImageThread implements Runnable {

		Socket writeImageSocket;
		OpenCVFrameGrabber grabber;

		public SendImageThread(Socket socket, OpenCVFrameGrabber grabber) {
			this.writeImageSocket = socket;
			this.grabber = grabber;

		}

		public void run() {
			IplImage image=null;
			DataOutputStream dos=null;
			try {
				dos = new DataOutputStream(writeImageSocket.getOutputStream());
				while ((image = grabber.grab()) != null && writeImageSocket.isConnected()) {
					ByteArrayOutputStream baos = new ByteArrayOutputStream();
					ImageIO.write(image.getBufferedImage(), "jpg", baos );
					baos.flush();
					byte[] imageInByte = baos.toByteArray(); 
					baos.close();
					
					dos.writeInt(imageInByte.length);
					dos.write(imageInByte,0,imageInByte.length);
					dos.flush();

				}

			} catch (IOException e) {
				e.printStackTrace();
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				try {
					if(dos!=null)dos.close();
					writeImageSocket.close();
				} catch (IOException e) {
					e.printStackTrace();
				}

			}

		}

	}
	
	public static void main(String[] args) {
		new CameraSever();
	}
}

android客户端代码

package com.example.imagetest;

import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import java.net.UnknownHostException;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.media.Image;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.StrictMode;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {
	private Button connectButton = null;
	private Socket clientSocket = null;
	private Handler mHandler = null;
	private ReceiveThread mReceiveThread = null;
	private ImageView iv;
	private Bitmap bitmap;

	/** Called when the activity is first created. */
	@SuppressLint("NewApi")
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		connectButton = (Button) this.findViewById(R.id.connectbutton);
		iv = (ImageView) findViewById(R.id.iv);
		if (android.os.Build.VERSION.SDK_INT > 9) {
			StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
					.permitAll().build();
			StrictMode.setThreadPolicy(policy);
		}
		connectButton.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				try {
					clientSocket = new Socket("127.0.0.1", 8888);//ip地址换成运行Camerasever.java程序的电脑的ip
				} catch (UnknownHostException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				}
				displayToast("连接成功!");
				try {
					mReceiveThread = new ReceiveThread(clientSocket);
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				mReceiveThread.start();

			}
		});
		// 消息处理
		mHandler = new Handler() {
			public void handleMessage(Message msg) {
				switch (msg.what) {
				case 1:
					iv.setImageBitmap(bitmap); // 在ImageView中显示Bitmap
					break;
				default:
					break;
				}
				super.handleMessage(msg);
			}
		};

	}

	// 显示Toast函数
	private void displayToast(String s) {
		Toast.makeText(this, s, Toast.LENGTH_SHORT).show();
	}

	private class ReceiveThread extends Thread implements OnClickListener {
		private Socket s;
		private Button button;
		private PrintWriter writer;
		private Boolean flag = false;
		DataInputStream dataInput;
		public ReceiveThread(Socket s) throws IOException {
			this.s=s;
			dataInput = new DataInputStream(
					s.getInputStream());
		}
			

		public void run() {
			try {
				while (true) {
					
					Log.e("5555555555555", "11111111111");
					int size = dataInput.readInt();
					Log.e("size in client", Integer.toString(size));
					byte[] data = new byte[size];
					int len = 0;
					while (len < size) {
						len += dataInput.read(data, len, size - len);
					}
					ByteArrayOutputStream outPut = new ByteArrayOutputStream();
					bitmap = BitmapFactory.decodeByteArray(data, 0,
							data.length);
					bitmap.compress(CompressFormat.PNG, 100, outPut);
					Message message = new Message();
					message.what = 1;
					mHandler.sendMessage(message);
//					Thread.sleep(100);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}

		}

		@Override
		public void onClick(View arg0) {
			// TODO Auto-generated method stub
			flag = true;
		}

	}

}

JavaCV的简介

JavaCV是一个开源的java语言实现的视觉计算库,封装了OpenCV,FFmpeg,libdc1394等常用的视觉计算库,使用也比较简单,相关文件可以到

https://code.google.com/p/javacv/downloads/list?can=1&q=&colspec=Filename+Summary+Uploaded+ReleaseDate+Size+DownloadCount下载,下载最新版本即可,其中javacv-examples-0.7-src.zip是该库作者提供的例子,供使用者学习,该库暂时没有文档;javacv-0.7-bin.zip是打包好的jar文件,需要引入javacpp.jar,javacv.jar,以及一个javacv-*.jar取决于系统,我用的是Windows8.1,64位,我用的是javacv-windows-x86_64.jar;javacv-0.7-cppjars.zip,是opencv的各版本的jar包,也是按照系统选择;javacv-0.7-src.zip是javacv的源代码,使用时导入即可。





你可能感兴趣的:(socket,视频,图片,pc,摄像头)