I have successfully integrated zxing Barcode scanner with Phonegap+sencha touch app. Now i have to capture the image also during the scan and return it to the view.
Thanks in Advance.
With ZXing APIs, you can implement it yourself. About how to use Android camera, please refer to Android website. Here is the code for capturing images from preview callback, as well as how to use zxing to decode the image:
private Camera.PreviewCallback mPreviewCallback = new PreviewCallback() {
#Override
public void onPreviewFrame(byte[] data, Camera camera) {
// TODO Auto-generated method stub
if (mDialog.isShowing())
return;
LuminanceSource source = new PlanarYUVLuminanceSource(data, mWidth, mHeight, mLeft, mTop, mAreaWidth, mAreaHeight, false);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(
source));
Result result;
try {
result = mMultiFormatReader.decode(bitmap, null);
if (result != null) {
mDialog.setTitle("Result");
mDialog.setMessage(result.getText());
mDialog.show();
}
} catch (NotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
For more detailed information, you can read the article How to implement a simple barcode scan application on Android
Related
I am trying to access the frames of the preview on Android using this Library, and then passing the FastJavaByteArray to Zxing's Decode() method to scan for a barcode in a specific area of the preview. The preview is working fine, and when I use the normal Preview.SetPreviewCallback(this); it works fine and the OnPreviewFrame(byte[], Camera) gets called. It's just when I use Preview.SetNonMarshalingPreviewCallback(this) that the method isn't being called. I'm not to sure why this is happening and I wanted to use this so I could scan for a barcode frame by frame using Zxing. I've attached my code below.
public void Open() {
if (!closed) return;
try {
Preview = Camera.Open();
}
catch (Exception e) {
Console.WriteLine(e);
}
var parameters = Preview.GetParameters();
int numBytes = (parameters.PreviewSize.Width * parameters.PreviewSize.Height * Android.Graphics.ImageFormat.GetBitsPerPixel(parameters.PreviewFormat)) / 8;
using (FastJavaByteArray buffer = new FastJavaByteArray(numBytes))
Preview.AddCallbackBuffer(new FastJavaByteArray(numBytes));
var options = new ZXing.Mobile.MobileBarcodeScanningOptions();
options.PossibleFormats.Add(BarcodeFormat.QR_CODE);
barcodeReader = options.BuildBarcodeReader();
Preview.SetNonMarshalingPreviewCallback(this);
//Preview.SetPreviewCallback(this);
Handler handler = new Handler();
Action loop = null;
loop = () =>
{
if (!closed)
{
AutoFocusLoop();
handler.PostDelayed(loop, (long)(1000 * AF_DELAY));
}
};
handler.Post(loop);
closed = false;
}
public void OnPreviewFrame(IntPtr data, Camera camera)
{
throw new NotImplementedException();
}
In My application using zxing library for scanning QR code but library can't support scanning white in black code(Negative scan) so please suggest me solution how can i resolve this issue.
Add below code, source.invert() will do your work
LuminanceSource source = new RGBLuminanceSource(bitmaps[0].getWidth(),
bitmaps[0].getHeight(), intArray);
BinaryBitmap bMap = new BinaryBitmap(new HybridBinarizer(source));
try {
result = reader.decode(bMap);
} catch (Exception e) {
BinaryBitmap bMap1 = new BinaryBitmap(new HybridBinarizer(source.invert()));
try {
result = reader.decode(bMap1);
} catch (NotFoundException notFoundException) {
// notFoundException.printStackTrace();
} catch (ChecksumException checksumException) {
//checksumException.printStackTrace();
} catch (FormatException formatException) {
//formatException.printStackTrace();
}
}
return result;
This question was asked but never answered here -- but it is somewhat different than my need, anyway.
I want to record video, while running the Google Vision library in the background, so whenever my user holds up a barcode (or approaches one closely enough) the camera will automatically detect and scan the barcode -- and all the while it is recording the video. I know the Google Vision demo is pretty CPU intensive, but when I try a simpler version of it (i.e. without grabbing every frame all the time and handing it to the detector) I'm not getting reliable barcode reads.
(I am running a Samsung Galaxy S4 Mini on KitKat 4.4.3 Unfortunately, for reasons known only to Samsung, they no longer report the OnCameraFocused event, so it is impossible to know if the camera grabbed the focus and call the barcode read then. That makes grabbing and checking every frame seem like the only viable solution.)
So to at least prove the concept, I wanted to simply modify the Google Vision Demo. (Found Here)
It seems the easiest thing to do is simply jump in the code and add a media recorder. I did this in the CameraSourcePreview method during surface create.
Like this:
private class SurfaceCallback implements SurfaceHolder.Callback
{
#Override
public void surfaceCreated(SurfaceHolder surface)
{
mSurfaceAvailable = true;
try
{
startIfReady();
if (mSurfaceAvailable)
{
Camera camera = mCameraSource.getCameraSourceCamera();
/** ADD MediaRecorder to Google Example **/
if (camera != null && recordThis)
{
if (mMediaRecorder == null)
{
mMediaRecorder = new MediaRecorder();
camera.unlock();
SurfaceHolder sh = mSurfaceView.getHolder();
mMediaRecorder.setPreviewDisplay(sh.getSurface());
mMediaRecorder.setCamera(camera);
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));
String OutputFile = Environment.getExternalStorageDirectory() + "/" +
DateFormat.format("yyyy-MM-dd_kk-mm-ss", new Date().getTime()) + ".mp4";
File newOutPut = getVideoFile();
String newOutPutFileName = newOutPut.getPath();
mMediaRecorder.setOutputFile(newOutPutFileName);
Log.d("START MR", OutputFile);
try { mMediaRecorder.prepare(); } catch (Exception e) {}
mCameraSource.mediaRecorder = mMediaRecorder;
mMediaRecorder.start();
}
}
}
}
catch (SecurityException se)
{
Log.e(TAG, "Do not have permission to start the camera", se);
}
catch (IOException e)
{
Log.e(TAG, "Could not start camera source.", e);
}
}
That DOES record things, while still handing each frame off to the Vision code. But, strangely, when I do that, the camera does not seem to call autofocus correctly, and the barcodes are not scanned -- since they are never really in focus, and therefore not recognized.
My next thought was to simply capture the frames as the barcode detector is handling the frames, and save them to the disk one by one (I can mux them together later.)
I did this in CameraSource.java.
This does not seem to be capturing all of the frames, even though I am writing them out in a separate AsyncTask running in the background, which I thought would get them eventually -- even if it took awhile to catch up. The saving was not optimized, but it looks as though it is dropping frames throughout, not just at the end.
To add this code, I tried putting it in the
private class FrameProcessingRunnable
in the run() method.
Right after the FrameBuilder Code, I added this:
if (saveImagesIsEnabled)
{
if (data == null)
{
Log.d(TAG, "data == NULL");
}
else
{
SaveImageAsync saveImage = new SaveImageAsync(mCamera.getParameters().getPreviewSize() );
saveImage.execute(data.array());
}
}
Which calls this class:
Camera.Size lastKnownPreviewSize = null;
public class SaveImageAsync extends AsyncTask<byte[], Void, Void>
{
Camera.Size previewSize;
public SaveImageAsync(Camera.Size _previewSize)
{
previewSize = _previewSize;
lastKnownPreviewSize = _previewSize;
}
#Override
protected Void doInBackground(byte[]... dataArray)
{
try
{
if (previewSize == null)
{
if (lastKnownPreviewSize != null)
previewSize = lastKnownPreviewSize;
else
return null;
}
byte[] bitmapData = dataArray[0];
if (bitmapData == null)
{
Log.d("doInBackground","NULL: ");
return null;
}
// where to put the output file (note: /sdcard requires WRITE_EXTERNAL_STORAGE permission)
File storageDir = Environment.getExternalStorageDirectory();
String imageFileName = baseFileName + "_" + Long.toString(sequentialCount++) + ".jpg";
String filePath = storageDir + "/" + "tmp" + "/" + imageFileName;
FileOutputStream out = null;
YuvImage yuvimage = new YuvImage(bitmapData, ImageFormat.NV21, previewSize.width,
previewSize.height, null);
try
{
out = new FileOutputStream(filePath);
yuvimage.compressToJpeg(new Rect(0, 0, previewSize.width,
previewSize.height), 100, out);
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
try
{
if (out != null)
{
out.close();
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
catch (Exception ex)
{
ex.printStackTrace();
Log.d("doInBackground", ex.getMessage());
}
return null;
}
}
I'm OK with the mediarecorder idea, or the brute force frame capture idea, but neither seem to be working correctly.
I am developing android application with facial recogniton using opencv library. My problem is the screen orientation. I got a solution with code below in JavaCameraView class.
mCamera.setDisplayOrientation(90);
mCamera.setPreviewDisplay(getHolder());
The camera is good but the facial detection doesnt work.
I found this but I think that the solution does not work in latest version of opencv library.
Any ideas could be useful.
Thanks in advance.
You have to also create the setDisplayOrientation by adding this:
protected void setDisplayOrientation(Camera camera, int angle){
Method downPolymorphic;
try
{
downPolymorphic = camera.getClass().getMethod("setDisplayOrientation", new Class[] { int.class });
if (downPolymorphic != null)
downPolymorphic.invoke(camera, new Object[] { angle });
}
catch (Exception e1)
{
}
}
I am using Android Zxing library to decode a QR code, that has to be extracted in real time from a camera preview frame. The problem is that I have to use OpenCV to do the QR code detection, without asking the user to capture the image. Can anybody please tell me:
How to use frames from a camera?
How to use OpenCV to do QR detection on these frames, without capturing the image?
What algorithm to use for QR code detection?
Also, I would appreciate if somebody can tell me what functions, libraries to use, as well as some sample codes that may help me.
Update: This is what I am doing now:
Using a preview frame, decoding it to Byte array, and then passing it to RGBLuminance
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, acquire the camera and tell it where
// to draw.
camera = Camera.open();
try {
camera.setPreviewDisplay(holder);
camera.setPreviewCallback(new PreviewCallback() {
public void onPreviewFrame(byte[] data, Camera arg1) {
boolean shouldCall = (System.currentTimeMillis() - lastTime) > 1000;
if (shouldCall) {
lastTime = System.currentTimeMillis();
//slow work
Camera.Parameters parameters = camera.getParameters();
Size size = parameters.getPreviewSize();
Bitmap bMap1 = BitmapFactory.decodeByteArray(data, 0, data.length);
TextView textv = (TextView) findViewById(R.id.mytext);
LuminanceSource source = new RGBLuminanceSource(bMap1);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
Reader reader = new MultiFormatReader();
try {
Result result = reader.decode(bitmap);
text = result.getText();
byte[] rawBytes = result.getRawBytes();
if (rawBytes!= null)
camera.stopPreview();
BarcodeFormat format = result.getBarcodeFormat();
ResultPoint[] points = result.getResultPoints();
ParsedResult result2 = parseResult(result);
textv.setText(text);
} catch (NotFoundException e) {
camera.startPreview();
e.printStackTrace();
} catch (ChecksumException e) {
text = "Checksum Error";
camera.stopPreview();
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FormatException e) {
text = "Format Error";
camera.stopPreview();
// TODO Auto-generated catch block
e.printStackTrace();
}
lastTime = System.currentTimeMillis();
}
}
});
} catch (IOException e) {
camera.startPreview();
}
}
But this isn't working. Can anybody tell me what I am doing wrong? Also, I am using the same decoding instance in my other code snippet, where I simply take a picture and decode it. But every time the picture doesn't contain a QR, the app crashes with a force close. What do I do about that? Somebody please help
Not sure, if you are using zxing already then you already have code that decodes QR codes from camera frames in Android, full stop. What else do you need -- why bother with OpenCV?