Ask Your Question

Revision history [back]

How can I work with my quickcam sphere AF on opencv ?

Hi, I am a french student and I actually work on a project that consists in use a quickcam sphere AF video flow to make some image treatment for a system of automatisation of a robot. The treatment have to be done on a dell streak 7 tablet under android 3.2 and the camera is mobile because it is on the robot that we make move (wifibot). Unfortunately my code give me some bitmap pictures but opencv only use Mat format...I guess...So I tried to convert that with bitmapToMat function but that makes crashing the application, or do nothing when I catch the exception.

Can we convert directly the flow received with http into Mat format? Or can we resolve the crashing problem?

Here is the original code to catch the video flow via http protocol:

package com.formation.wfbt_ctrl;

import android.graphics.Paint; 
import android.graphics.Canvas;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.Properties;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

import org.opencv.core.Mat;

public class MjpegInputStream extends DataInputStream {
    private final byte[] SOI_MARKER = { (byte) 0xFF, (byte) 0xD8 };
    private final byte[] EOF_MARKER = { (byte) 0xFF, (byte) 0xD9 };
    private final String CONTENT_LENGTH = "Content-Length";
    private final static int HEADER_MAX_LENGTH = 100;
    private final static int FRAME_MAX_LENGTH = 40000 + HEADER_MAX_LENGTH;
    private int mContentLength = -1;


    public static MjpegInputStream read(String url) {
        HttpResponse res;
        DefaultHttpClient httpclient = new DefaultHttpClient();     
        try {
            res = httpclient.execute(new HttpGet(URI.create(url)));
            return new MjpegInputStream(res.getEntity().getContent());              
        } catch (ClientProtocolException e) {
        } catch (IOException e) {}
        return null;
    }

    public MjpegInputStream(InputStream in) { super(new BufferedInputStream(in, FRAME_MAX_LENGTH)); }

    private int getEndOfSequence(DataInputStream in, byte[] sequence) throws IOException {
        int seqIndex = 0;
        byte c;
        for(int i=0; i < FRAME_MAX_LENGTH; i++) {
            c = (byte) in.readUnsignedByte();
            if(c == sequence[seqIndex]) {
                seqIndex++;
                if(seqIndex == sequence.length) return i + 1;
            } else seqIndex = 0;
        }
        return -1;
    }

    private int getStartOfSequence(DataInputStream in, byte[] sequence) throws IOException {
        int end = getEndOfSequence(in, sequence);
        return (end < 0) ? (-1) : (end - sequence.length);
    }

    private int parseContentLength(byte[] headerBytes) throws IOException, NumberFormatException {
        ByteArrayInputStream headerIn = new ByteArrayInputStream(headerBytes);
        Properties props = new Properties();
        props.load(headerIn);
        return Integer.parseInt(props.getProperty(CONTENT_LENGTH));
    }   

    public Bitmap readMjpegFrame() throws IOException {
        mark(FRAME_MAX_LENGTH);
        int headerLen = getStartOfSequence(this, SOI_MARKER);
        reset();
        byte[] header = new byte[headerLen];
        readFully(header);
        try {
            mContentLength = parseContentLength(header);
        } catch (NumberFormatException nfe) { 
            mContentLength = getEndOfSequence(this, EOF_MARKER); 
        }
        reset();
        byte[] frameData = new byte[mContentLength];
        skipBytes(headerLen);
        readFully(frameData);

       /* BitmapFactory.Options opts = new BitmapFactory.Options();
        opts.inPreferredConfig = Bitmap.Config.ARGB_8888;

        Mat res = new Mat();
        res.put(640, 480, frameData);*/

        Bitmap res = BitmapFactory.decodeStream(new ByteArrayInputStream(frameData)/*,null,opts*/);

        /*Bitmap convertedBitmap = Bitmap.createBitmap(res.getWidth(), res.getHeight(), Bitmap.Config.RGB_565);
        Canvas canvas = new Canvas(convertedBitmap);
        Paint paint = new Paint();
        canvas.drawBitmap(res, 0, 0, paint);

        return convertedBitmap;//*/return res;

    }

}

And there is the view which shows the video

package com.formation.wfbt_ctrl;

import java.io.IOException;

import org.opencv.android.Utils;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.imgproc.Imgproc;
import org.opencv.core.CvException;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View.OnTouchListener;
import android.view.View;
import android.view.MotionEvent;
import android.widget.Toast;

//import android.graphics.Rect;
import android.graphics.Matrix;
import org.opencv.core.Rect;
import org.opencv.android.Utils;
import org.opencv.core.MatOfByte;

public class MjpegView2 extends SurfaceView implements SurfaceHolder.Callback {
    public final static int POSITION_UPPER_LEFT  = 9;
    public final static int POSITION_UPPER_RIGHT = 3;
    public final static int POSITION_LOWER_LEFT  = 12;
    public final static int POSITION_LOWER_RIGHT = 6;

    public final static int SIZE_STANDARD   = 1; 

    private MjpegViewThread thread;
    private MjpegInputStream mIn = null;    
    private boolean mRun = false;
    private boolean surfaceDone = false;    
    private int dispWidth;
    private int dispHeight;

    Bitmap bm = Bitmap.createBitmap(640, 480, Bitmap.Config.ARGB_8888);
 //   Mat mRgba = new Mat();

    private static final String  TAG              = "OCVSample::Activity";
    private boolean              mIsColorSelected = false;
    private Mat                  mRgba;
    private Scalar               mBlobColorRgba;
    private Scalar               mBlobColorHsv;
    private ColorBlobDetector    mDetector;
    private Mat                  mSpectrum;
    private Size                 SPECTRUM_SIZE;
    private Scalar               CONTOUR_COLOR;

    public class MjpegViewThread extends Thread {
        private SurfaceHolder mSurfaceHolder;
        public MjpegViewThread(SurfaceHolder surfaceHolder, Context context) { mSurfaceHolder = surfaceHolder; }

        private Rect destRect(int bmw, int bmh) {
            int tempx = (dispWidth / 2) - (bmw / 2);
            int tempy = (dispHeight / 2) - (bmh / 2);
            return new Rect(tempx, tempy, bmw + tempx, bmh + tempy);
        }

        public void setSurfaceSize(int width, int height) {
            synchronized(mSurfaceHolder) {
                dispWidth = width;
                dispHeight = height;
            }
        }

        public void run() {

            //Bitmap bm;
            Mat mouah;
            Rect destRect;
            Canvas c = null;
            Paint p = new Paint();
            Matrix m = new Matrix();
            while (mRun) {
                if(surfaceDone) {
                    try {
                        c = mSurfaceHolder.lockCanvas();
                        synchronized (mSurfaceHolder) {
                            try {
                                bm = mIn.readMjpegFrame();
                                destRect = destRect(bm.getWidth(),bm.getHeight());
                                c.drawColor(Color.WHITE);
                                c.drawBitmap(bm,m,p);

                         //       Bitmap res = JPEGtoRGB888(bm);
                         //       Utils.bitmapToMat(res,mRgba,true);

                            } catch (CvException e) {}
                            catch(IOException e){}
                        }
                    } finally { if (c != null) mSurfaceHolder.unlockCanvasAndPost(c); }
                }
            }
        }
    }

    private void init(Context context) {
        SurfaceHolder holder = getHolder();
        holder.addCallback(this);
        thread = new MjpegViewThread(holder, context);
        setFocusable(true);
      //  displayMode = MjpegView.SIZE_STANDARD;
        dispWidth = getWidth();
        dispHeight = getHeight();

    }

    public void startPlayback() { 
        if(mIn != null) {
            mRun = true;
            thread.start();         
        }
    }

    public void stopPlayback() { 
        mRun = false;
        boolean retry = true;
        while(retry) {
            try {
                thread.join();
                retry = false;
            } catch (InterruptedException e) {}
        }
    }

    public MjpegView2(Context context, AttributeSet attrs) { super(context, attrs); init(context); }
    public void surfaceChanged(SurfaceHolder holder, int f, int w, int h) { thread.setSurfaceSize(w, h); }

    public void surfaceDestroyed(SurfaceHolder holder) { 
        surfaceDone = false; 
        stopPlayback(); 
    }

    public MjpegView2(Context context) { super(context); init(context); }    
    public void surfaceCreated(SurfaceHolder holder) { surfaceDone = true; }
    public void setSource(MjpegInputStream source) { mIn = source; startPlayback();}

    private Bitmap JPEGtoRGB888(Bitmap img)
    {
            int numPixels = img.getWidth()* img.getHeight();
            int[] pixels = new int[numPixels];

        //Get JPEG pixels.  Each int is the color values for one pixel.
            img.getPixels(pixels, 0, img.getWidth(), 0, 0, img.getWidth(),img.getHeight());

        //Create a Bitmap of the appropriate format.
        Bitmap result = Bitmap.createBitmap(img.getWidth(),img.getHeight(), Bitmap.Config.ARGB_8888);

        //Set RGB pixels.
        result.setPixels(pixels, 0, result.getWidth(), 0, 0,result.getWidth(), result.getHeight());
        return result;
    }

}

Voila, thank you for your attention :)