精华内容
下载资源
问答
  • cms网络摄像头客户端

    2019-03-18 17:54:56
    网络摄像头客户端,功能强大,适合大多数网络摄像头,推荐使用
  • 魅色软件是一款可以让手机作为电脑摄像头利用的工具.假如你的电脑上没有摄像头,魅色无疑是一款非常棒的应急软件.目前pc版本和android最新版本为4.3 ,手机支持无线wifi和usb有线两种衔接方法
  • 多品牌摄像机PC多画面监控,IP地址搜索修改,支持雄迈,中维,天视通等方案。
  • 查看PC实时摄像头视频,其实就是以大于24次/秒的速度,控制PC摄像头进行拍照,并把每一张拍得的图片发送到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的源代码,使用时导入即可。





    展开全文
  • 手机摄像头变成PC电脑摄像头 工具 硬件:一台手机(Android,IOS),一根数据线(或者处于同一局域网),一台PC机(Windows,Linux(Ubuntu18.04)) 软件:DroidCam Mobile client PC client 安装 手机端和Windows ...

    手机摄像头变成PC电脑摄像头

    工具

    硬件:一台手机(Android,IOS),一根数据线(或者处于同一局域网),一台PC机(Windows,Linux(Ubuntu18.04))
    软件:DroidCam Mobile client PC client

    安装

    手机端和Windows 安装比较傻瓜, Ubuntu 安装按照英文教程安装就可以了

    使用

    如果使用网络就没有很麻烦,只要让两个客户端处于同一局域网即可启动

    使用USB数据线连接,Android 手机需要开启开发者调试模式(可能有的小伙伴找不到这个功能,这是因为手机厂商把开发者调试模式给关了,这时我们需要找到设置中的关于手机的版本号,连续点击几次,就会看到提示)
    在这里插入图片描述
    在这里插入图片描述

    值得一提的是linux的好多功能(旋转等)都是免费的, 而Windows 则需要下载增强版本才能使用这些功能
    在这里插入图片描述
    在这里插入图片描述

    测试

    一个挺不错的测试网站
    在这里插入图片描述

    展开全文
  • 手机端打开摄像头实时预览 手机端作为服务端,PC端作为客户端连接, 连接成功后PC端可以同时预览手机端的摄像头采集的图像 PC端点击拍照可以控制手机端拍摄一张照片,并将照片传给PC
  • 手机摄像头PC端)

    2011-11-01 11:32:36
    在安卓系统上可用的变手机摄像头的软件,简单易用,支持WIFI,此为PC端,手机端详见我的其它下载。
  • (2)手机端作为服务端,PC端作为客户端连接; (3)连接成功后PC端可以同时预览手机端的摄像头采集的图像; (4)PC端点击拍照可以控制手机端拍摄一张照片,并将照片传给PC端。 2 功能模块 (1)安卓手机打开摄像头...

    1 功能需求

    (1)手机端打开摄像头实时预览;
    (2)手机端作为服务端,PC端作为客户端连接;
    (3)连接成功后PC端可以同时预览手机端的摄像头采集的图像;
    (4)PC端点击拍照可以控制手机端拍摄一张照片,并将照片传给PC端。

    2 功能模块

    (1)安卓手机打开摄像头并实现预览和拍照功能;
    (2)手机端开启监听,并在连接成功后将摄像头采集的数据传给PC;
    (3)手机端读取PC发送的命令指令,执行相应的操作。

    3 开发流程

    3.1 开启摄像头实现预览
    (1) 获取摄像头权限,并添加自动对焦属性。
      在应用程序的manifest.xml文件中添加使用手机摄像头权限。由于程序需要使用socket的通信过程,将手机作为服务端,因此需要添加网络权限。

    <uses-permission android:name="android.permission.CAMERA" />
     <uses-feature android:name="android.hardware.camera" />  
     <uses-feature android:name="android.hardware.camera.autofocus" />
     <uses-permission Android:name="android.permission.INTERNET"/>
    

    2)实现相机的实时预览。
       安卓系统使用SurfaceView即可完成预览功能。在布局文件中添加SurfaceView。activity_main.xml布局文件如下:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/gray_light"
    android:orientation="vertical" >
    
    <SurfaceView
        android:id="@+id/surview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:scaleType="fitCenter" />
    
    </LinearLayout>
    

    (3)在MainActivity 的onCreate中初始化SurfceView。初始化方法如下:

    private void initSurfaceView() {
        surfaceView = (SurfaceView) findViewById(R.id.surview);
        surfaceHolder = surfaceView.getHolder();
        surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        surfaceHolder.setKeepScreenOn(true);
        surfaceHolder.addCallback(new Callback() {
    
            @Override
            public void surfaceDestroyed(SurfaceHolder arg0) {
    
            }
    
            @Override
            public void surfaceCreated(SurfaceHolder arg0) {
                // 开启摄像头
                startCamera(curCameraIndex);
            }
    
            @Override
            public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2,
                    int arg3) {
    
            }
        });
        surfaceView.setFocusable(true);
        surfaceView.setBackgroundColor(TRIM_MEMORY_BACKGROUND);
    
    }
    

    4)SurfceView创建完成时调用开启摄像头的方法startCamera()。startCamera方法如下,其中代码含义已在注释程序中注明。

    // 根据索引初始化摄像头
    @SuppressLint("NewApi")
    public void startCamera(int cameraIndex) {
    
        // 先停止摄像头
        stopCamera();
        // 再初始化并打开摄像头
        if (camera == null) {
            //打开手机摄像头,cameraIndex为摄像头索引,0代表后置摄像头,1代表前置摄像头。
            camera = Camera.open(cameraIndex);
            //创建摄像头操作工具类
            cameraUtil = new CameraUtil(camera, callback);
            //开启预览
            cameraUtil.initCamera(srcFrameHeight, srcFrameWidth, surfaceHolder);
            Log.e(TAG, "打开相机");
        }
    }
    
    // 停止并释放摄像头
    public void stopCamera() {
        if (camera != null) {
            camera.setPreviewCallback(null);
            camera.stopPreview();
            camera.release();
            camera = null;
        }
    }
    
    //摄像头开启预览后采集到的数据回调接口
    PreviewCallback callback = new PreviewCallback() {
    
        @Override
        public void onPreviewFrame(byte[] data, Camera camera) {
            Size size = camera.getParameters().getPreviewSize();
            try {
                if (times == 0) {
                    YuvImage image = new YuvImage(data, ImageFormat.NV21,
                            size.width, size.height, null);
                    if (image != null) {
                        // 将YuvImage对象转为字节数组
                        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                        image.compressToJpeg(new Rect(0, 0, size.width,
                                size.height), 100, outputStream);
                        byte[] srcData = outputStream.toByteArray();
                        int len = srcData.length;
    
                        // 字节数组转为Bitmap
                        Bitmap src = BitmapFactory.decodeByteArray(srcData, 0,
                                len);
                        src = BitmapUtil.rotate(src, 90);
                        // 压缩Bitmap,并获取压缩后的字节数组,即可获取预览数据文件
                        // outdata数据即是待发送给PC端的数据
                        byte[] outdata = BitmapUtil.transImage(src,
                                srcFrameWidth / 4, srcFrameHeight / 4);
                        int datalen = outdata.length;
    
                        if (isOpen) {
                            // 写入头
                            sendData(new byte[] { (byte) 0xA0 });
                            // 写入数组长度
                            sendData(intToByteArray(datalen));
                            // 写入数据值
                            sendData(outdata);
                        }
    
                        // 回收Bitmap
                        if (!src.isRecycled()) {
                            src.recycle();
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    };
    

    (5)CameraUtil为设置摄像头的辅助类,代码如下:

    public class CameraUtil {
        //摄像头类
        Camera camera;
        int cameraIndex;
        //预览视图宽和高
        int srcFrameWidth;
        int srcFrameHeight;
        SurfaceHolder surfaceHolder;
        PreviewCallback callback;
    
        public CameraUtil(Camera camera, PreviewCallback callback) {
            this.camera = camera;
            this.callback = callback;
           }
    
        //摄像头预览初始化
        public void initCamera(final int srcFrameWidth, final int srcFrameHeight, final SurfaceHolder surfaceHolder) {
    
            this.srcFrameHeight = srcFrameHeight;
            this.srcFrameWidth = srcFrameWidth;
            this.surfaceHolder = surfaceHolder;
            Camera.Parameters params = camera.getParameters();
            //params.setPreviewSize(srcFrameWidth / 4, srcFrameHeight / 4);
            //设置预览格式
            params.setPreviewFormat(ImageFormat.NV21);
            params.setPreviewFrameRate(30);
            //设置图像质量
            params.setJpegQuality(100);
            params.setPictureFormat(ImageFormat.JPEG);
            //设置预览方向
            params.set("orientation", "portrait");
            params.set("rotation", 90);
            //设置对焦模式为自动连续对焦
            params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);// 1连续对焦
            camera.setParameters(params);
            camera.setDisplayOrientation(90);
            // 设置显示图像的SurfaceView
            try {
                camera.setPreviewDisplay(surfaceHolder);
            } catch (IOException e) {
                e.printStackTrace();
            }
            camera.setPreviewCallback(callback);
            //启动预览
            camera.startPreview();
            camera.autoFocus(new AutoFocusCallback() {
            @Override
            public void onAutoFocus(boolean result, Camera camera) {
    
                // 自动对焦完成时回调
                if (result) {
                        initCamera(srcFrameWidth, srcFrameHeight, surfaceHolder);
                        camera.cancelAutoFocus();
                    }
                }
            });
        }
    
        @SuppressLint("NewApi") 
        public void startCamera(int cameraIndex) {
    
            this.cameraIndex = cameraIndex;
            // 先停止摄像头
            stopCamera();
            // 再初始化并打开摄像头
            if (camera == null) {
                camera = Camera.open(cameraIndex);
                initCamera(srcFrameWidth, srcFrameHeight, surfaceHolder);       
            }
        }
    
        //停止预览
        public void stopCamera() {
            if (camera != null) {
                camera.setPreviewCallback(null);
                camera.stopPreview();
                camera.release();
                camera = null;
            }
        }
    }
    

    6)BitmapUtil为图片操作辅助类

    public class BitmapUtil {
    
        // Bitmap按照一定大小转为字节数组,以便写入socket进行发送
        public static byte[] transImage(Bitmap bitmap, int width, int height) {
            // bitmap = adjustPhotoRotation(bitmap, 90);
            try {
                int bitmapWidth = bitmap.getWidth();
                int bitmapHeight = bitmap.getHeight();
                float scaleWidth = (float) width / bitmapWidth;
                float scaleHeight = (float) height / bitmapHeight;
                Matrix matrix = new Matrix();
                matrix.postScale(scaleWidth, scaleHeight);
                // 创建压缩后的Bitmap
                Bitmap resizeBitemp = Bitmap.createBitmap(bitmap, 0, 0,
                    bitmapWidth, bitmapHeight, matrix, false);
    
                // 压缩图片质量
                ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                resizeBitemp.compress(CompressFormat.JPEG, 80, outputStream);
                // 转为字节数组
                byte[] byteArray = outputStream.toByteArray();
                outputStream.close();
    
                // 回收资源
                if (!bitmap.isRecycled()) {
                    bitmap.recycle();
                }
                if (!resizeBitemp.isRecycled()) {
                    resizeBitemp.recycle();
                }
                return byteArray;
    
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            return null;
        }
    
        //图片旋转操作
        public static Bitmap rotate(Bitmap bitmap, float degree) {
            Matrix matrix = new Matrix();
           // matrix.setScale(0.5f, 0.5f);// 缩小为原来的一半
            matrix.postRotate(degree);// 旋转45度 == matrix.setSinCos(0.5f, 0.5f);
            bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
            bitmap.getHeight(), matrix, true);
            return bitmap;
        }
    }
    

    3.2 连接手机与PC

    手机与PC的连接实际上是使用socket通信完成的。将手机端作为服务器开启监听。PC端发起连接,通过adb命令的端口转换将PC的连接请求发送至手机,建立手机与PC的连接。主要操作流程如下:

    (1) onCreate中注册广播的监听
    注册广播监听主要是接收PC端调用adb发送的广播信息,用于通知手机端开启监听和停止监听。

    IntentFilter filter = new IntentFilter();
        filter.addAction("NotifyServiceStart");
        filter.addAction("NotifyServiceStop");
        registerReceiver(receiver, filter);
    

    (2) 接收系统广播

    public class ServiceBroadcastReceiver extends BroadcastReceiver {
    
        private static final String START_ACTION = "NotifyServiceStart";
        private static final String STOP_ACTION = "NotifyServiceStop";
    
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (START_ACTION.equalsIgnoreCase(action)) {
                // 启动服务
                Log.e(TAG, "收到广播信息启动监听");
                new Thread() {
                    public void run() {
    
                        if (serverSocket != null) {
                            try {
                                serverSocket.close();
                            } catch (IOException e) {
    
                                e.printStackTrace();
                            }
                        }
                        //服务端启动监听
                        doListen();
                    };
                }.start();
    
            } else if (STOP_ACTION.equalsIgnoreCase(action)) {
    
            }
        }
    }
    

    (3)启动监听
    手机端作为服务端,启动监听。注意对于网络的操作不能在主线程中。启动监听的方法doListen()如下:

    // 启动服务器端监听
        private void doListen() {
            serverSocket = null;
            try {
                serverSocket = new ServerSocket(SERVER_PORT);
                while (true) {
                    Socket socket = serverSocket.accept();
                    Log.e(TAG, "监听到设备连接,启动通信线程");
                    //PC端连接成功,启动通信线程ThreadReadWriterIOSocket
                    threadSocket = new ThreadReadWriterIOSocket(socket);
                    new Thread(threadSocket).start();
                }
            } catch (IOException e) {
                Log.e(TAG, "服务端监听失败");
                e.printStackTrace();
            }
        }
    

    4)ThreadReadWriterIOSocket为负责通信的线程。
    ThreadReadWriterIOSocket是实现了Runnable接口的一个线程,其主要任务就是接收PC端发送的命令信息,并将命令信息通过EventBus框架发送至主界面。

    public class ThreadReadWriterIOSocket implements Runnable {
    
        private static String TAG = "ThreadReadWriterIOSocket";
        private Socket client;
        private BufferedOutputStream out;
        private BufferedInputStream in;
        boolean isConnecting = false;
        private String cmd = "";
    
        public ThreadReadWriterIOSocket(Socket client) {
            this.client = client;
        }
    
        @Override
        public void run() {
    
            Log.e(TAG, "有客户端连接上");
            isConnecting = true;
            try {
                // 获取输入输出流
                out = new BufferedOutputStream(client.getOutputStream());
                in  = new BufferedInputStream(client.getInputStream());
    
                // 循环等待,接受PC端的命令
                while (isConnecting) {
                    try {
                        if (!client.isConnected()) {
                            break;
                        }
                        // 读取命令
                        cmd = readCMDFromSocket(in);    
                        Log.e(TAG, "读取到PC发送的命令" + cmd);
                        /* 根据命令分别处理数据 */
                        if (cmd.equals(Constant.CONNECT)) {// 收到连接命令
                            EventBus.getDefault().post(new MessageEvent(Constant.START));
                            out.flush();
                        } else if (cmd.equalsIgnoreCase(Constant.DISCONNECT)) {// 断开命令
                            EventBus.getDefault().post(new MessageEvent(Constant.STOP));
                            out.flush();
                        }else if (cmd.equals(Const    ant.TAKEPHOTO)) {//拍照命令
                            EventBus.getDefault().post(new MessageEvent(Constant.TAKEPHOTO));
                            out.flush();
                        }
                        in.reset();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                out.close();
                in.close();
            } catch (Exception e) {
                e.printStackTrace();
            } 
        }
    
        public void cancel() {
            isConnecting = false;
        }
    
        //发送数据
        public void writeData(byte[] data) {
            if (out != null) {
                try {
                    out.write((data));
                } catch (IOException e) {
                    Log.e(TAG, "输入输出异常");
                    e.printStackTrace();
                }
            }
        }
    
        /* 读取命令 */
        public String readCMDFromSocket(InputStream in) {
    
            int MAX_BUFFER_BYTES = 2048;
            String msg = "";
            byte[] tempbuffer = new byte[MAX_BUFFER_BYTES];
            try {
                int numReadedBytes = in.read(tempbuffer, 0, tempbuffer.length);
                msg = new String(tempbuffer, 0, numReadedBytes, "utf-8");
                tempbuffer = null;
            } catch (Exception e) {
                Log.e(TAG, "readCMDFromSocket读数异常" + e.toString());
                EventBus.getDefault().post(new MessageEvent(Constant.DISCONNECT));
                e.printStackTrace();
            }
            return msg;
        }
    }
    

    (5)主界面接收EventBus传递的命令信息
    通信的通知过程采用EventBus实现,在主界面中注册EventBus。
    onCreate中注册EventBus

    EventBus.getDefault().register(this);
    

    创建onMessageEvent方法实现事件处理函数,并将事件处理交给主线程。

    @Subscribe(threadMode = ThreadMode.MAIN)
        public void onMessageEvent(MessageEvent event) {
            switch (event.message) {
            case Constant.DISCONNECT://断开命令
    
                Toast.makeText(MainActivity.this, "客户端断开", Toast.LENGTH_LONG)
                        .show();
                threadSocket.cancel();
    
            case Constant.START://收到连接命令
    
                isOpen = true;
                Toast.makeText(MainActivity.this, "客户端连接上", Toast.LENGTH_LONG)
                        .show();
                startCamera(curCameraIndex);
    
                break;
            case Constant.STOP://收到断开命令
    
                stopCamera();
                isOpen = false;
    
                break;
            case Constant.TAKEPHOTO://收到拍照命令
    
                if (isOpen) {
                    camera.takePicture(new ShutterCallback() {
    
                        @Override
                        public void onShutter() {
    
                        }
                    }, new Camera.PictureCallback() {
    
                        @Override
                        public void onPictureTaken(byte[] arg0, Camera arg1) {
    
                        }
                    }, new Camera.PictureCallback() {
    
                        @Override
                        public void onPictureTaken(byte[] data, Camera camera) {
    
                            // 向电脑端发送数据
                            int datalen = data.length;
                            if (isOpen) {
                                // 写入数据头
                                sendData(new byte[] { (byte) 0xA1 });
                                // 写入数组长度
                                sendData(intToByteArray(datalen));
                                // 写入数据值
                                sendData(data);
                            }
                            // 重新开启预览
                            camera.stopPreview();
                            camera.startPreview();
                        }
                    });
    
                }
    
            }
        }   
    

    6)当建立连接之后可以向PC端发送数据。
    数据的发送需要调用ThreadReadWriterIOSocket的write方法,将图像信息数据发送给PC。发送方法sendData如下:

    public void sendData(final byte[] data) {
            threadSocket.writeData(data);
        }
    

    3.3 PC端发起连接

    PC端作为客户端需要向服务端发起连接。PC的端的程序使用Java实现。主函数代码如下:

     public class Main {
    
            //用于通信的socket
            private static Socket socket;
            //输入输出数据流
            private static OutputStream out;
            private static InputStream in;
            public  static MyFrame frame;
            private static String CMD = "";
    
            public static void main(String[] args) {
    
                //创建界面
                frame = new MyFrame();
                //添加连接按钮
                JPanel panel2 = new JPanel();
                panel2.setLayout(new FlowLayout(FlowLayout.CENTER, 10, 0));
                final JButton button = new JButton("连接");
                panel2.add(button);
                button.addActionListener(new ActionListener() {
                    @Override
                public void actionPerformed(ActionEvent arg0) {
                    new Thread() {
                        public void run() {
                                //点击连接按钮,PC端发起连接
                                onConnect();
                            };
                        }.start();
                        button.setEnabled(false);
                    }
                });
                //创建断开按钮
                JButton button2 = new JButton("断开");
                button2.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent arg0) {
    
                        //发送断开命令
                        CMD = Constant.DISCONNECT;
                        try {
                            out.flush();
                            out.write(CMD.getBytes());
                            out.flush();                
                        } catch (IOException e) {
    
                            e.printStackTrace();
                        }
                        button.setEnabled(true);
                    }
                });
                panel2.add(button2);
    
                //创建拍照按钮
                JButton button3 = new JButton("拍照");
                button3.addActionListener(new ActionListener() {
    
                    @Override
                    public void actionPerformed(ActionEvent arg0) {
                        //发送拍照命令
                        CMD = Constant.TAKEPHOTO;
                        try {
                            out.flush();
                            out.write(CMD.getBytes());
                            out.flush();                    
                        } catch (IOException e) {   
                            e.printStackTrace();
                        }           
                    }
                });
                panel2.add(button3);
    
                frame.add(panel2, BorderLayout.SOUTH);
                frame.setResizable(false);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setVisible(true);
            }
    
            //启动连接时使用adb发送系统广播
            protected static void onConnect() {
                try {
                    //adb指令,发送NotifyServiceStop广播,手机接收到此广播停止监听
                    Runtime.getRuntime().exec(
                        "adb shell am broadcast -a NotifyServiceStop");
                    Thread.sleep(2000);
                    //调用adb的端口转换命令,将PC端发起的tcp连接指向手机服务器
                    Runtime.getRuntime().exec("adb forward tcp:12580 tcp:10086"); // 端口转换
                    Thread.sleep(2000);
                    //发送NotifyServiceStart广播,手机接收到此广播启动监听
                    Runtime.getRuntime().exec(
                        "adb shell am broadcast -a NotifyServiceStart");
                    Thread.sleep(3000);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                int len = 0;
                int degree = 0;
                try {
                    //PC端发起TCP连接
                    InetAddress serveraddr = null;
                    serveraddr = InetAddress.getByName("127.0.0.1");
                    System.out.println("TCP 1 " + "正在连接。。。。");
                    socket = new Socket(serveraddr, 12580);
                    System.out.println("TCP 2 " + "连接成功 ");
                    // 获取输入输出流
                    out = new BufferedOutputStream(socket.getOutputStream());
                    in  = new BufferedInputStream(socket.getInputStream());
                    // 发送连接命令
                    CMD = Constant.CONNECT;
                    out.write(CMD.getBytes());
                    out.flush();
                    boolean flag = true;    
                    if (socket.isConnected()) {
                        while (flag) {
                            try {
                                int head = in.read();
    
                                if (head == 0xA0) {//获取数据头
                                    byte[] src = new byte[4];
                                    len = in.read(src);
                                    len = byteArrayToInt(src);//获取数据长度
                                    if (len > 0) {
                                        int cclen = 0;
                                        byte[] srcData = new byte[len];
                                        while (cclen < len) {
                                            int readlen = in.read(srcData, cclen, len
                                                - cclen);
                                            cclen += readlen;
                                        }
                                        //将图像数据转为ImageIcon对象
                                        ImageIcon icon = new ImageIcon(srcData);
                                    if (icon != null) {
                                        //显示图像
                                        frame.setIcon(icon, degree);
                                    }
                                }
                                }else if (head == 0xA1) {//获取数据头
                                    byte[] src = new byte[4];
                                    len = in.read(src);
                                    len = byteArrayToInt(src);//获取数据长度
                                    if (len > 0) {
                                        int cclen = 0;
                                        byte[] srcData = new byte[len];
                                        while (cclen < len) {
                                            int readlen = in.read(srcData, cclen, len
                                                - cclen);
                                            cclen += readlen;
                                        }
    
                                        //保存图片文件
                                        File file = new File("D:\\images\\" + System.currentTimeMillis() + ".jpg");
                                        if (!file.exists()) {
                                            file.mkdirs();
                                        }
                                        //存储图片                      
                                        ImageIcon icon = new ImageIcon(srcData);
                                        Image image = icon.getImage();
                                        BufferedImage bi = new BufferedImage(image.getWidth(null),image.getHeight(null),BufferedImage.TYPE_INT_RGB);
                                        Graphics2D g2d = bi.createGraphics();
                                        g2d.drawImage(image, 0, 0, null);
                                        g2d.dispose();
                                        ImageIO.write(bi,"jpg",file);
                                    }
                                }
    
                            } catch (Exception e) {
    
                            }
    
                        }
                    }
                } catch (Exception e1) {
                    System.out.println(" 连接出现异常:连接失败: " + e1.toString());
                }
            }
    
            public static int byteArrayToInt(byte[] b) {
                return b[3] & 0xFF | (b[2] & 0xFF) << 8 | (b[1] & 0xFF) << 16
                    | (b[0] & 0xFF) << 24;
            }
        }
    

    MyFrame类:

    public class MyFrame extends JFrame {
    
            private static final long serialVersionUID = 1L;
            public MyPanel panel;
    
            public MyFrame() {
    
                // 默认的窗体名称
                this.setTitle("USB连接显示");
    
                // 获得面板的实例
                panel = new MyPanel();
                this.add(panel);
    
                this.pack();
                this.setVisible(true);
            }
    
            //设置图片
            public void setIcon(ImageIcon incon, int drgree) {  
                panel.setImage(incon, drgree);
            }
        }
    

    MyPanel类:

     public class MyPanel extends Panel {
    
            private static final long serialVersionUID = 1L;
            private Image bufferImage;
            private final Image screenImage = new BufferedImage(800, 600, 2);
            private final Graphics2D screenGraphic = (Graphics2D) screenImage
                .getGraphics();
            int degree = 90;
            private Image backgroundImage = screenImage;
    
            public MyPanel() {
                // 设定焦点在本窗体
                setFocusable(true);
                // 设定初始构造时面板大小,这里先采用图片的大小
                setPreferredSize(new Dimension(800, 600));
                // 绘制背景
                drawView();
            }
    
            public void setImage(ImageIcon icon, int degree) {
    
                //System.out.println("设置图片   偏转角度" + degree);
                this.degree = degree;
                backgroundImage = icon.getImage();
                drawView();
                repaint();
            }
    
            private void drawView() {
                int width  = getWidth();
                int height = getHeight();
    
                int x = width / 2 - backgroundImage.getWidth(null) /2;
                int y = height / 2 - backgroundImage.getHeight(null) / 2;
                screenGraphic.drawImage(backgroundImage, x , y, null);
            }
    
            @Override
            public void update(Graphics g) {
    
                if (bufferImage == null) {
                    bufferImage = this.createImage(this.getWidth(), this.getHeight());
                }
    
                //bufferImage = rotateImage(bufferimage, degree);
    
                Graphics gBuffer = bufferImage.getGraphics();// 获得图片缓冲区的画笔
                if (gBuffer != null){
                    paint(gBuffer);
                }
                else{
                    paint(g);
                }
                gBuffer.dispose();
                g.drawImage(bufferImage, 0, 0, null);
            }
    
            //显示图像
            public void paint(Graphics g) {
                g.drawImage(screenImage, 0, 0, null);
            }
    
    
            public static BufferedImage rotateImage(final BufferedImage bufferedimage,
                final int degree) {
                int w = bufferedimage.getWidth();
                int h = bufferedimage.getHeight();
                int type = bufferedimage.getColorModel().getTransparency();
                BufferedImage img;
                Graphics2D graphics2d;
                (graphics2d = (img = new BufferedImage(w, h, type))
                    .createGraphics()).setRenderingHint(
                    RenderingHints.KEY_INTERPOLATION,
                    RenderingHints.VALUE_INTERPOLATION_BILINEAR);
                graphics2d.rotate(Math.toRadians(degree), w / 2, h / 2);
                graphics2d.drawImage(bufferedimage, 0, 0, null);
                graphics2d.dispose();
                return img;
            }
        }
    

    两个工程均用到的Constant类

    public class Constant {
            public static final String addrIp = "192.168.0.119";
            public static final int addrPort = 56168;
            public static final String CONNECT = "CONNECT";
            public static final String DISCONNECT = "DISCONNECT";
            public static final String TAKEPHOTO = "TAKEPHOTO";
            public static final String START = "START";
            public static final String STOP = "STOP";
        }
    

    需要源码的同学可以找我,怎么找我呢。接着看:
    针对Android程序员,除了上面的知识体系,我也分享一份私货,分享我从网络上收录整理的 Android学习PDF+架构视频+面试文档+源码笔记 ,还有Android开发面试专题资料,高级进阶架构资料供大家学习进阶
    学习资料可以进群找我:434543138。当然都是免费的,备注来处就行。
    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • 3.Android手机做于视频的客户端,当然也可以用普通PC了;   软件配置: 1.首先刷路由器的固件,我刷了Tomato DualWAN 。刷新方法网上的教程很多。 2.连接USB摄像头, 为路由器添加视频支持,大至过程如下:  ...
      
    

     硬件方面:

    1.可刷固件的带USB接口路由器,我用的是电信装宽带送的中兴H618b;

    2.普通USB摄像头,我的芯片是ZC303;

    3.Android手机做于视频的客户端,当然也可以用普通PC了;

     

    软件配置:

    1.首先刷路由器的固件,我刷了Tomato DualWAN 。刷新方法网上的教程很多。

    2.连接USB摄像头, 为路由器添加视频支持,大至过程如下:

        a.下载视频相关文件;

        b.启用路由器USB,JTAG和SSH功能;

        c.上传相关文件到路由器的JFFS目录;

        d.设置视频相关脚本,并测试。

        以上是对启用视频方法的总结,详细方法可以在网上找教程。

     3.视频监控客户端:

     如果是普通PC,不管是Linux还是Windows系统,可以使用SpcaView直接连接视频。

        对于Android手机,权限SpcaView的相关协议自己写了一个APK通过Socket实现。

       对于IPhone手机,理论上移植也没有问题,暂时还没研究。

     

    另外,也可以把相应的Jar包和Html上传到路由器的Web目录,然后通过浏览器直接查看视频。

    由于路由器的权限问题我没办法进行测试。

     

    总结:

    视频服务器端使用了Linux下的SpcaServer,也就是为Linux添加视频驱动,然后启动服务就行了。

    由于是开源的还可以自已进行修改。

     

    客户端对应的是SpcaView,这个在PC端Linux 和Windows下都有人移植成功,Android端需要自己开发。

    开发基本上是把JWebcamPlayer.java的代码整理一下就好了。

     

     

    展开全文
  • NV 网络PC摄像头 1.0版

    2014-04-28 08:51:19
    电脑摄像头服务程序,可以让局域网内的客户访问,一个服务程序可以让五个客户端同时访问。 没有源代码,工具使用。
  • 本站之前分享过一个PC端动态演示手机屏幕的源码,点击PC项目分类目录就可以找到,本项目是一套PC端动态演示手机摄像头图像的源码,在电脑上先运行服务端,手机需要和电脑在一个网络中,打开安卓端以后会要求配置一个...
  • andriod 手机当电脑摄像头 USBWebCam

    热门讨论 2011-02-13 16:33:15
    andriod 手机当电脑摄像头 USBWebCam 包括客户端PC端 运行PC端,连接USB线 ,打开客户端 ,记得打开USB debug模式 .可用于QQ聊天摄像头.
  • 这个是用Html5的fieldapi做的,客户端比例缩放,批量上传图片。减少服务器压力,客户端通过base64预览。并且支持直接调用手机相册摄像头 注意:代码里面做了判断,如果是pc端使用flash压缩,如果移动端使用H5进行缩放
  • 1. 安装PC桌面客户端手机端程序 2. 运行PC桌面客户端手机端程序 3. 手机PC在同一局域网内上网 4. 先运行PC软件,再运行手机程序,此时手机端程序会自动搜索同局域网内的PC软件 5. 如果没有自动连接,请: 在...
  • 为您提供牵心PC客户端下载,牵心PC客户端是这款牵心智能摄像机的配套软件,支持远程视频传输、移动侦测报警、高清视频回放等功能,一款懂你的摄像机!软件特色 【高清视频】画面清晰放大不模糊,视频流畅连续不卡顿...
  • [教程] 充分发挥手机500W像素优势发个真正可以实现安卓做PC摄像头的教材 软件 不喜勿喷 好长时间没来了 今天显得难受 从网上 偶尔发现一个 可以把安卓手机作为PC 摄像头的 软件 亲测可用哦 还不错 就推荐...
  • PC网络版人脸识别解决方案 可应用解决方案: 智慧校园、智慧工地、智慧社区、智慧景区等 优势:既支持USB摄像头或网络摄像头,可以同时支持1~16路摄像头,支持和已有系统进行对接 通过PC网络版人脸识别客户端自动...
  • 网络摄像机PC客户端,提供豪飞IPC视频预览,系统配置,录像等功能
  • 手机摄像头图像源码

    2021-03-16 18:05:48
    手机摄像头图像源码是一套PC端动态演示手机摄像头图像的源码,在电脑上先运行服务端,手机需要和电脑在一个网络中,打开安卓端以后会要求配置一个ip地址,把PC的IP地址填入手机,点击登录以后服务端控制台会循环打印...
  • 两步让安卓手机变成无线摄像头。 1.安装压缩包中PC客户端 2.安装手机客户端。 3.启动手机客户端(记住屏幕上的IP地址) 4.启动PC客户端,输入IP及端口,点击connect。 成功后开QQ视频测试下吧。 很方便的无线摄像头...
  • 海思网络摄像机PC 客户端DEMO

    热门讨论 2014-06-16 22:30:17
    海思网络摄像机客户端DEMO 软件,包括云台控制,图像参数,IP 地址查询,抓拍等网络控制,如添加音频和P2P ONVIF ,TF 卡存储等功能也可以,设备硬件可以全套提供,这样可以完善的开发学习应用,设备的SDK 对接协议和...
  • 这个是camhi电请填写资源的Tag脑端的最新版本,亲测可用!可以添加远程摄像头,也可以使用这个客户端录像,这是最新版的,支持H265编码格式
  • ip摄像头pc

    2018-03-10 09:04:29
    XXCAMERA摄像头电脑端软件。ip摄像机pc端软件。ip摄像机pc端控制端。
  • 这篇我们来做个小实验,实现开发板上运行服务端,可以直接控制led灯,客户端通过socket连接到服务端,通过发送指令来远程控制服务端的led灯。我们用平台总线的思想来编写驱动程序,这里分为LED平台驱动程序和LED平台...
  • 手机摄像头图像源码是一套PC端动态演示手机摄像头图像的源码,在电脑上先运行服务端,手机需要和电脑在一个网络中,打开安卓端以后会要求配置一个ip地址,把PC的IP地址填入手机,点击登录以后服务端控制台会循环打印...
  • 使用Python和picamera实现树莓派/PC实时摄像头数据共享,主要也可分为服务器和客户端两部分。
  • 方法一:Python+OpenCv实现树莓派数据采集,树莓派搭建服务器,PC机作为客户端实现数据传输,结果发现传输画质太差。 网址:https://blog.csdn.net/m0_38106923/article/details/81974373 方法二:使...
  • 这里搜集了两种实现Android 手机采集摄像头视频 socket 视频传输实时传播的方法,两种都可以使用。 第一种如下: 1.通过客户端socket请求,服务端接受到请求后,获取socket的输出流对象outs。 2.服务端通过Camera...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,204
精华内容 2,481
关键字:

手机pc摄像头客户端