怎么把摄像机图像测试里的图像传到手机里

摄像机识别图片中的手机号 - liyyanli - 博客园
项目布局中使用:SurfaceView:宽,高都填充窗体
1.相机预览的实现
2.相机自动聚焦实现
(1)/article/da4513fdf47504.html
这个楼主是在SurfaceView的触摸事件中添加了自动对焦事件。
首先创建回调方法,代码如下:
&随时调用回调方式1:
按钮调用:就是在点击某一按钮后实现自动对焦。只需要在按钮的触发事件中使用camera回调(mCamera.autoFocusCallback(myAutoFocusCallback&))即可。
随时调用回调方式2:
触屏调用:设置surfaceView的触屏事件,在该事件中实现camera回调。
一:先写好获取相机对象的方法,释放相机资源的方法
* 获取Camera的对象
public Camera getCamera() {
camera = Camera.open();
} catch (Exception e) {
camera = null;
e.printStackTrace();
* 开始预览相机内容
private void setStartPreview(Camera camera, SurfaceHolder holder) {
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPictureFormat(ImageFormat.JPEG);
parameters.setPictureSize(800, 480);
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
camera.setPreviewDisplay(holder);
camera.setParameters(parameters);
camera.setPreviewCallback(this);
camera.setOneShotPreviewCallback(this);
camera.setDisplayOrientation(90);
camera.startPreview();
camera.autoFocus(myAutoFocus);
} catch (IOException e) {
e.printStackTrace();
* 释放相机资源
private void releaseCamera() {
if (mCamera != null) {
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mCamera.release();
mCamera = null;
if (mHolder != null) {
二:SurfaceHolder.Callback需要重写的方法。
* A client may implement this interface to receive information about
* changes to the surface.
When used with a {@link SurfaceView}, the
* Surface being held is only available between calls to
* {@link #surfaceCreated(SurfaceHolder)} and
* {@link #surfaceDestroyed(SurfaceHolder)}.
The Callback is set with
* {@link SurfaceHolder#addCallback SurfaceHolder.addCallback} method.
public interface Callback {
* This is called immediately after the surface is first created.
* Implementations of this should start up whatever rendering code
* they desire.
Note that only one thread can ever draw into
* a {@link Surface}, so you should not draw into the Surface here
* if your normal rendering will be in another thread.
* @param holder The SurfaceHolder whose surface is being created.
public void surfaceCreated(SurfaceHolder holder);
* This is called immediately after any structural changes (format or
* size) have been made to the surface.
You should at this point update
* the imagery in the surface.
This method is always called at least
* once, after {@link #surfaceCreated}.
* @param holder The SurfaceHolder whose surface has changed.
* @param format The new PixelFormat of the surface.
* @param width The new width of the surface.
* @param height The new height of the surface.
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height);
* This is called immediately before a surface is being destroyed. After
* returning from this call, you should no longer try to access this
* surface.
If you have a rendering thread that directly accesses
* the surface, you must ensure that thread is no longer touching the
* Surface before returning from this function.
* @param holder The SurfaceHolder whose surface is being destroyed.
public void surfaceDestroyed(SurfaceHolder holder);
三:让Activity页面实现SurfaceHolder.Callback,里面的方法
public void surfaceCreated(SurfaceHolder holder) {
setStartPreview(mCamera, mHolder);
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
mCamera.stopPreview();
setStartPreview(mCamera, mHolder);
13 @Override
public void surfaceDestroyed(SurfaceHolder holder) {
releaseCamera();
四:自定义CameraView继承SurfaceView来封装好对应的SurfaceHolder.Callback回调
import java.io.IOE
import android.content.C
import android.hardware.C
import android.hardware.Camera.AutoFocusC
import android.hardware.Camera.PreviewC
import android.util.L
import android.view.SurfaceH
import android.view.SurfaceV
/** A basic Camera preview class */
public class CameraPreview extends SurfaceView implements
SurfaceHolder.Callback {
private SurfaceHolder mH
private Camera mC
private PreviewCallback previewC
private AutoFocusCallback autoFocusC
@SuppressWarnings("deprecation")
public CameraPreview(Context context, Camera camera,
PreviewCallback previewCb, AutoFocusCallback autoFocusCb) {
super(context);
previewCallback = previewCb;
autoFocusCallback = autoFocusCb;
* Set camera to continuous focus if supported, otherwise use software
* auto-focus. Only works for API level &=9.
* Camera.Parameters parameters = camera.getParameters(); for (String f
* : parameters.getSupportedFocusModes()) { if (f ==
* Parameters.FOCUS_MODE_CONTINUOUS_PICTURE) {
* mCamera.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
* autoFocusCallback = } }
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the
// preview.
mCamera.setPreviewDisplay(holder);
} catch (IOException e) {
Log.d("DBG", "Error setting camera preview: " + e.getMessage());
public void surfaceDestroyed(SurfaceHolder holder) {
// Camera preview released in activity
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
* If your preview can change or rotate, take care of those events here.
* Make sure to stop the preview before resizing or reformatting it.
if (mHolder.getSurface() == null) {
// preview surface does not exist
// stop preview before making changes
mCamera.stopPreview();
} catch (Exception e) {
// ignore: tried to stop a non-existent preview
// Hard code camera surface rotation 90 degs to match Activity view
// in portrait
mCamera.setDisplayOrientation(90);
mCamera.setPreviewDisplay(mHolder);
mCamera.setPreviewCallback(previewCallback);
mCamera.startPreview();
mCamera.autoFocus(autoFocusCallback);
} catch (Exception e) {
Log.d("DBG", "Error starting camera preview: " + e.getMessage());
五:获取相机预览时的照片;要实现PreviewCallback的回调
(一)http://blog.csdn.net/ocean20/article/details/8772196 原楼主分享
Camera.PreviewCallback:定义了onPreviewFrame(byte[]&data,&Camera&camera)&方法,当存在预览帧(preview&frame)时调用该方法。可以传入保存当前图像像素的字节数组。在Camera对象上,有3种不同的方式使用这个回调:
&&setPreviewCallback(Camera.PreviewCallback):使用此方法注册一个Camera.&PreviewCallback,这将确保在屏幕上显示一个新的预览帧时调用onPreviewFrame方法。传递到onPreviewFrame方法中的数据字节数组最有可能采用YUV格式。但是,&2.2是第一个包含了YUV格式解码器(YuvImage)的版本;在以前的版本中,必须手动完成解码。
&&setOneShotPreviewCallback(Camera.PreviewCallback):利用Camera对象上的这个方法注册Camera.PreviewCallback,从而当下一幅预览图像可用时调用一次onPreviewFrame。同样,传递到onPreviewFrame方法的预览图像数据最有可能采用YUV格式。可以通过使用ImageFormat中的常量检查Camera.&getParameters().&getPreviewFormat()返回的结果来确定这一点。
&&setPreviewCallbackWithBuffer(Camera.PreviewCallback):在Android&2.2中引入了该方法,其与setPreviewCallback的工作方式相同,但要求指定一个字节数组作为缓冲区,用于预览图像数据。这是为了能够更好地管理处理预览图像时使用的内存。
●&Camera.AutoFocusCallback:定义了onAutoFocus方法,当完成一个自动聚焦活动时调用它。通过传入此回调接口的一个实例,在调用Camera对象上的autoFocus方法时会触发自动聚焦。
●&Camera.ErrorCallback:定义了onError方法,当发生一个Camera错误时调用它。有两个常量可用于与传入的错误代码进行比较:CAMERA_ERROR_UNKNOWN和CAMERA_ERROR_SERVER_DIED。
●&Camera.OnZoomChangeListener:定义了onZoomChange方法,当正在进行或完成&平滑缩放&(慢慢缩小或放大)时调用它。在Android&2.2&(API&Level&8)中引入了这个类和方法。
Camera.ShutterCallback:定义了onShutter方法,当捕获图像时立刻调用它
(二)源码:需要实现onPreviewFrame方法;在这个方法中,可以获取预览时的图片btye字节数组。
* Callback interface used to deliver copies of preview frames as
* they are displayed.
* @see #setPreviewCallback(Camera.PreviewCallback)
* @see #setOneShotPreviewCallback(Camera.PreviewCallback)
* @see #setPreviewCallbackWithBuffer(Camera.PreviewCallback)
* @see #startPreview()
* @deprecated We recommend using the new {@link android.hardware.camera2} API for new
applications.
@Deprecated
public interface PreviewCallback
* Called as preview frames are displayed.
This callback is invoked
* on the event thread {@link #open(int)} was called from.
* &p&If using the {@link android.graphics.ImageFormat#YV12} format,
* refer to the equations in {@link Camera.Parameters#setPreviewFormat}
* for the arrangement of the pixel data in the preview callback
* buffers.
* @param data the contents of the preview frame in the format defined
by {@link android.graphics.ImageFormat}, which can be queried
with {@link android.hardware.Camera.Parameters#getPreviewFormat()}.
If {@link android.hardware.Camera.Parameters#setPreviewFormat(int)}
is never called, the default will be the YCbCr_420_SP
(NV21) format.
* @param camera the Camera service object.
void onPreviewFrame(byte[] data, Camera camera);
(三)原项目中处理
public void onPreviewFrame(byte[] data, Camera camera) {
Camera.Parameters parameters = camera.getParameters();
int width = parameters.getPreviewSize().
int height = parameters.getPreviewSize().
ByteArrayOutputStream outstr = new ByteArrayOutputStream();
Rect rect = new Rect(0, 0, width, height);
YuvImage yuvimage = new YuvImage(data, ImageFormat.NV21, width, height, null);
pressToJpeg(rect, 100, outstr);
Bitmap bmp = BitmapFactory.decodeByteArray(outstr.toByteArray(), 0, outstr.size());
Matrix matrix = new Matrix();
matrix.setRotate(90);
bmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true);
bmp = Bitmap.createBitmap(bmp, capture_crop_rl.getLeft(), capture_crop_rl.getTop(),
capture_crop_rl.getRight(), capture_crop_rl.getBottom(), matrix, true);*/
/*bit_result = Bitmap.createBitmap(bmp,capture_crop_rl.getLeft(),capture_crop_rl.getTop()
, capture_crop_rl.getRight(),capture_crop_rl.getBottom());//截取*/
if(null != mBitmapFaceTask){
switch(mBitmapFaceTask.getStatus()){
case RUNNING:
case PENDING:
mBitmapFaceTask.cancel(false);
mBitmapFaceTask = new BitmapFaceTask(data);
mBitmapFaceTask.execute((Void)null);
/*自定义的FaceTask类,开启一个线程分析数据*/
private class BitmapFaceTask extends AsyncTask&Void, Void, Void& {
private byte[] mD
//构造函数
BitmapFaceTask(byte[] data){
this.mData =
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
Camera.Size size = mCamera.getParameters().getPreviewSize(); //获取预览大小
final int w = size.
final int h = size.
final YuvImage image = new YuvImage(mData, ImageFormat.NV21, w, h, null);
ByteArrayOutputStream os = new ByteArrayOutputStream(mData.length);
if(!pressToJpeg(new Rect(0, 0, w, h), 100, os)){
return null;
byte[] tmp = os.toByteArray();
getBitmap = BitmapFactory.decodeByteArray(tmp, 0,tmp.length);
//设置FOCUS_MODE_CONTINUOUS_VIDEO)之后,myParam.set("rotation", 90)失效。图片竟然不能旋转了,故这里要旋转下
Matrix matrix = new Matrix();
matrix.postRotate((float)90.0);
Bitmap rotaBitmap = Bitmap.createBitmap(getBitmap, 0, 0, getBitmap.getWidth(), getBitmap.getHeight(), matrix, false);
//将960&1280缩放到540&800
getBitmap = Bitmap.createScaledBitmap(rotaBitmap, 540, 800, true);
getBitmap = rotaB
runOnUiThread(new Runnable() {
public void run() {
left= StringUtil.px2dip(CropPhoneNumberActivity.this,capture_crop_rl.getLeft());
top=StringUtil.px2dip(CropPhoneNumberActivity.this,capture_crop_rl.getTop());
right=StringUtil.px2dip(CropPhoneNumberActivity.this,capture_crop_rl.getRight());
buttom=StringUtil.px2dip(CropPhoneNumberActivity.this,capture_crop_rl.getBottom()+TitleBar.getStatusBarHeight());
/****top=top-px2dip(CropPhoneNumberActivity.this,TitleBar.getStatusBarHeight());
* 经常取到的top为0
bit_result = Bitmap.createBitmap(getBitmap, left, top,
right, buttom);
Matrix matrix = new Matrix();
matrix.postScale(2f,2f); //长和宽放大缩小的比例
bit_result = Bitmap.createBitmap(bit_result,0,0,bit_result.getWidth(),bit_result.getHeight(),matrix,true);
createPhoneText();
return null;
/**** 该handler用于处理修改结果的任务******/
private void createPhoneText() {
photouri= ImageUtils.createFilename();
ImageUtils.saveImage(CropPhoneNumberActivity.this,bit_result,photouri);
iv_image.setImageBitmap(bit_result);
// 新线程来处理识别
new Thread(new Runnable() {
public void run() {
/*对图像进行预处理*/
/*bitmap_end_result = ImgPretreatment
.doPretreatment(bit_result);*/
/*将图片化成灰度图*/
/*bitmapTreated = ImgPretreatment
.converyToGrayImg(bitmapSelected);*/
if(null!=bit_result)
textResult = doOcr(bit_result,LANGUAGE);
runOnUiThread(new Runnable() {
public void run() {
GetToast.showToast(mContext,textResult);
Message msg = new Message();
msg.what = SHOWRESULT;
myHandler.sendMessage(msg);
}).start();
public static Handler myHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case SHOWRESULT:
if (TextUtils.isEmpty(textResult)) {
//Toast.makeText(mContext, "识别失败", Toast.LENGTH_SHORT).show();
}else if(textResult.length()&=11){
//这里只截取了:成功情况下的手机号在末尾的11位中。
textResult=textResult.substring(textResult.length()-11,textResult.length());
if(StringUtil.isMobilePhone(textResult)) {
setText(textResult);
//Toast.makeText(mContext,"号码格式不正确",Toast.LENGTH_SHORT).show();
//Toast.makeText(mContext, "号码长度不够", Toast.LENGTH_SHORT).show();
super.handleMessage(msg);
使用了开源的特征库(需要存放到手机sd卡根目录下);在摄像机预览状态下获取扫描手机号框框区域内的图片bitmap对象,交给开源代码识别数字,识别出来的数字进入手机号的正则表达式匹配
在识别手机号的过程中,为了增加识别率:可以参照的文章有:http://www.oschina.net/code/snippet_67 & 楼主使用c语言写的
不过思路以后可以参考一下
&发布于 日 15时,&
一个图片识别小工具,原先主要是识别以前公司的软件注册码截图里的数字和字母(每次要一个一个框复制出来粘贴到注册器里,很麻烦!),因为注册码出现的字母和数字基本就那几个,所以识别库的范围设定的比较少。原理和算法在代码中做了详细说明,功能存在很大的局限性,但我的想法是把这个思路和实现的办法共享出来。源码下载地址:http://git.oschina.net/bobo2cj/iamge2text
1.&[图片]&主界面.png& &&
2.&[代码]提取出该图片内的字符 & &&
22 /// &summary&
23 /// 提取出该图片内的字符(将进过灰度处理的图片转化为0、1的二位数组)
24 /// &/summary&
25 /// &param name="singlepic"&图片来源&/param&
26 public void generateLicense(Bitmap singlepic)
char[,] charArray = new char[singlepic.Height, singlepic.Width];
//定义个chai型的二维数组记录每个像素上0/1的值,形成一个矩形
int imageWidth = 0;
//记录图片的像素宽度
int imageHeight = 0;
//记录图片的像素高度
int dgGrayValue = 128;
//string code = "";
//存储每个像素的0/1
for (int posy = 0; posy & singlepic.H posy++)
{//从上到下
string codeCache = "";
//存储每行的像素的0/1
for (int posx = 0; posx & singlepic.W posx++)
{//从左到右
piexl = singlepic.GetPixel(posx, posy);
if (piexl.R & dgGrayValue)
{// 如果该像素的颜色为黑色,值就为&1&
codeCache = codeCache + "1";
{// 否则该像素的颜色为白色,值就为&0&
codeCache = codeCache + "0";
char[] array = codeCache.ToCharArray();
//每行的0/1的值用数字保存,以便于进行循环处理
//code += codeCache + "\n";
for (imageWidth = 0; imageWidth & array.L imageWidth++)
charArray[imageHeight, imageWidth] = array[imageWidth];
//通过循环将每行值转存到二维数组中
imageHeight++;
//*********************以上代码可用来获取一个字的图片二进制数组,即字库*****************************
//开始和字库进行匹配(我的工具中只需要下面的几个字符)
findWord(charArray, char0, imageHeight, imageWidth, BinaryWidth0, BinaryHeight0, '0');
findWord(charArray, char1, imageHeight, imageWidth, BinaryWidth1, BinaryHeight1, '1');
findWord(charArray, char2, imageHeight, imageWidth, BinaryWidth2, BinaryHeight2, '2');
findWord(charArray, char3, imageHeight, imageWidth, BinaryWidth3, BinaryHeight3, '3');
findWord(charArray, char4, imageHeight, imageWidth, BinaryWidth4, BinaryHeight4, '4');
findWord(charArray, char5, imageHeight, imageWidth, BinaryWidth5, BinaryHeight5, '5');
findWord(charArray, char6, imageHeight, imageWidth, BinaryWidth6, BinaryHeight6, '6');
findWord(charArray, char7, imageHeight, imageWidth, BinaryWidth7, BinaryHeight7, '7');
findWord(charArray, char8, imageHeight, imageWidth, BinaryWidth8, BinaryHeight8, '8');
findWord(charArray, char9, imageHeight, imageWidth, BinaryWidth9, BinaryHeight9, '9');
findWord(charArray, charA, imageHeight, imageWidth, BinaryWidthA, BinaryHeightA, 'a');
findWord(charArray, charB, imageHeight, imageWidth, BinaryWidthB, BinaryHeightB, 'b');
findWord(charArray, charC, imageHeight, imageWidth, BinaryWidthC, BinaryHeightC, 'c');
findWord(charArray, charD, imageHeight, imageWidth, BinaryWidthD, BinaryHeightD, 'd');
findWord(charArray, charE, imageHeight, imageWidth, BinaryWidthE, BinaryHeightE, 'e');
findWord(charArray, charF, imageHeight, imageWidth, BinaryWidthF, BinaryHeightF, 'f');
findWord(charArray, charP, imageHeight, imageWidth, BinaryWidthP, BinaryHeightP, 'p');
findWord(charArray, charY, imageHeight, imageWidth, BinaryWidthY, BinaryHeightY, 'y');
//------------------------------------END---------------------------------------------
richTextBoxLicense.Text += identifySort();
//执行identifySort方法,将我需要的格式在richTextBoxLicense文本框中显示
richTextBoxLicense.SelectionStart = richTextBoxLicense.TextL
//将光标移到最后面
3.&[图片]&单个字图片对应的二维矩阵0、1码.png&&&&
自己切图后;并不能保证图片的字体跟上述的一致;所以不能达到需求。
* 开发思路:图片灰度处理,二进制,然后和图片中的字二进制库精确对比
* 获取字库:通过下面代码中generateLicense(Bitmap singlepic)方法获得,具体操作:
从图片中截图出(抠出)一个字符,然后处理得到二维的二进制矩阵,比如下面的字符1对应的二维矩阵
* 注意:【相同字符,比如1,不同字体,字号,不同缩放大小的图片,获得到的二位矩阵中0、1排列和数量都是不同的!
故按照此方法来写出匹配所有字的话,那字库就大了。。。】
21 */static String stringByte0 = "";
static char[] char0 = stringByte0.toCharArray();
static int BinaryWidth0 = 5, BinaryHeight0 = 11;
//0的平面像素长宽(从0开始数起)
static String stringByte1 = "";
static char[] char1 = stringByte1.toCharArray();
static int BinaryWidth1 = 4, BinaryHeight1 = 11;
//1的平面像素长宽(从0开始数起)
static String stringByte2 = "";
static char[] char2 = stringByte2.toCharArray();
static int BinaryWidth2 = 4, BinaryHeight2 = 11;
//2的平面像素长宽(从0开始数起)
static String stringByte3 = "";
static char[] char3 = stringByte3.toCharArray();
static int BinaryWidth3 = 4, BinaryHeight3 = 11;
//3的平面像素长宽(从0开始数起)
static String stringByte4 = "";
static char[] char4 = stringByte4.toCharArray();
static int BinaryWidth4 = 5, BinaryHeight4 = 11;
//4的平面像素长宽(从0开始数起)
static String stringByte5 = "";
static char[] char5 = stringByte5.toCharArray();
static int BinaryWidth5 = 4, BinaryHeight5 = 11;
//5的平面像素长宽(从0开始数起)
static String stringByte6 = "";
static char[] char6 = stringByte6.toCharArray();
static int BinaryWidth6 = 5, BinaryHeight6 = 11;
//6的平面像素长宽(从0开始数起)
static String stringByte7 = "";
static char[] char7 = stringByte7.toCharArray();
static int BinaryWidth7 = 4, BinaryHeight7 = 11;
//7的平面像素长宽(从0开始数起)
static String stringByte8 = "";
static char[] char8 = stringByte8.toCharArray();
static int BinaryWidth8 = 5, BinaryHeight8 = 11;
//8的平面像素长宽(从0开始数起)
static String stringByte9 = "";
static char[] char9 = stringByte9.toCharArray();
static int BinaryWidth9 = 5, BinaryHeight9 = 11;
//9的平面像素长宽(从0开始数起)
static int[][] intStartXY = new int[128][3];
//记录匹配上时的&X坐标&和&Y坐标&对应的&值&以及该&字符像素的宽度&
static int numIdentfied = 0;
//负责记录总共有多少匹配的字符
/*****Android SDK中提供了Bitmap图片每个像素颜色读取的方法:*/
/*public void getPixColor(){
Bitmap src =
BitmapFactory.decodeResource(getResources(),R.drawable.imgbg);
int A, R, G, B;
int pixelC
int height = src.getHeight();
int width = src.getWidth();
for (int y = 0; y & y++) {
for (int x = 0; x & x++) {
pixelColor = src.getPixel(x, y);
A = Color.alpha(pixelColor);
R = Color.red(pixelColor);
G = Color.green(pixelColor);
B = Color.blue(pixelColor);
Log.e("A:", A+"");
Log.e("R:", R+"");
Log.e("G:", G+"");
Log.e("B:", B+"");
//提取数字码
private void GenerateText(Bitmap mBitmap)
Bitmap Sourcebm = (Bitmap)mBitmap.I
//为了保险起见将pictureBox的图片类型进行格式转换(Bitmap)
int iw = mBitmap.getWidth();
//图片宽度
int ih = mBitmap.getHeight();
//图片高度
/* //下面双循环是图片灰度处理
for (int i = 0; i & i++)
{//从左到右
for (int j = 0; j & j++)
{//从上到下
//Color c = mBitmap.GetPixel(i, j);
//获取该点的颜色
//int luma = (int)(c.R * 0.3 + c.G * 0.59 + c.B * 0.11);
//将颜色转换为数值体现
int colorPix=mBitmap.getPixel(i,j);
int alpha=Color.alpha(colorPix);
//将颜色转换为数值体现
int luma = (int)(Color.red(colorPix) * 0.3 + Color.green(colorPix) * 0.59 + Color.blue(colorPix)* 0.11);
//将这一点进行灰度处理,非白色的部分变黑
//mBitmap.setPixel(i, j, Color.FromArgb(luma, luma, luma));
mBitmap.setPixel(i, j, Color.argb(alpha,luma, luma, luma));
generateLicense(mBitmap);
//通过该方法进行提取字符
}catch(Exception e){
GetToast.showToast(mContext,"提取图片出错了");
/// 提取出该图片内的字符(将进过灰度处理的图片转化为0、1的二位数组)
/// &param name="singlepic"&图片来源&/param&
public void generateLicense(Bitmap singlepic)
photouri= ImageUtils.createFilename();
ImageUtils.saveImage(CropPhoneNumberActivity.this,singlepic,photouri);
iv_image.setImageBitmap(singlepic);
String richTextBox="";
//定义个chai型的二维数组记录每个像素上0/1的值,形成一个矩形
char[][] charArray = new char[singlepic.getHeight()][singlepic.getWidth()];
int imageWidth = 0;
//记录图片的像素宽度
int imageHeight = 0;
//记录图片的像素高度
int dgGrayValue = 128;
//string code = "";
//存储每个像素的0/1
for (int posy = 0; posy & singlepic.getHeight(); posy++)
{//从上到下
String codeCache = "";
//存储每行的像素的0/1
for (int posx = 0; posx & singlepic.getWidth(); posx++)
{//从左到右
piexl = singlepic.getPixel(posx, posy);
if (Color.red(piexl)& dgGrayValue)
{// 如果该像素的颜色为黑色,值就为&1&
codeCache = codeCache + "1";
{// 否则该像素的颜色为白色,值就为&0&
codeCache = codeCache + "0";
char[] array = codeCache.toCharArray();
//每行的0/1的值用数字保存,以便于进行循环处理
//code += codeCache + "\n";
for (imageWidth = 0; imageWidth & array. imageWidth++)
charArray[imageHeight][imageWidth] = array[imageWidth];
//通过循环将每行值转存到二维数组中
imageHeight++;
//*********************以上代码可用来获取一个字的图片二进制数组,即字库*****************************
//开始和字库进行匹配(我的工具中只需要下面的几个字符)
findWord(charArray, char0, imageHeight, imageWidth, BinaryWidth0, BinaryHeight0, '0');
findWord(charArray, char1, imageHeight, imageWidth, BinaryWidth1, BinaryHeight1, '1');
findWord(charArray, char2, imageHeight, imageWidth, BinaryWidth2, BinaryHeight2, '2');
findWord(charArray, char3, imageHeight, imageWidth, BinaryWidth3, BinaryHeight3, '3');
findWord(charArray, char4, imageHeight, imageWidth, BinaryWidth4, BinaryHeight4, '4');
findWord(charArray, char5, imageHeight, imageWidth, BinaryWidth5, BinaryHeight5, '5');
findWord(charArray, char6, imageHeight, imageWidth, BinaryWidth6, BinaryHeight6, '6');
findWord(charArray, char7, imageHeight, imageWidth, BinaryWidth7, BinaryHeight7, '7');
findWord(charArray, char8, imageHeight, imageWidth, BinaryWidth8, BinaryHeight8, '8');
findWord(charArray, char9, imageHeight, imageWidth, BinaryWidth9, BinaryHeight9, '9');
//------------------------------------END---------------------------------------------
richTextBox += identifySort();
//执行identifySort方法,将我需要的格式在richTextBoxLicense文本框中显示
GetToast.showToast(mContext,"::richTextBox::"+richTextBox);
}catch(Exception e) { }
/// 和字库进行匹配
/// &param name="charArray"&记录图片中每个像素的二维数组&/param&
/// &param name="charNum"&字库中0/1值一维数组形式的字符&/param&
/// &param name="imageHeight"&图片的像素高度&/param&
/// &param name="imageWidth"&图片的像素宽度&/param&
/// &param name="binaryWidth"&字库中该字符的像素宽度&/param&
/// &param name="binaryHeight"&字库中该字符的像素高度&/param&
/// &param name="stringChar"&字库中该字符&/param&
public void findWord(char[][] charArray, char[] charNum, int imageHeight, int imageWidth, int binaryWidth, int binaryHeight, char stringChar)
int upLeftX, upLeftY, x,
for (y = 0; y & imageHeight - binaryH y++)//从图片的每行开始
for (x = 0; x & imageWidth - binaryW x++)//从当前行的第一格开始
boolean isIdentified = false;
//负责辨别是否匹配
int count = 0;
//负责计数
for (upLeftY = 0; upLeftY &= binaryH upLeftY++)//从图片中取出一块进行对比,从的每行开始
for (upLeftX = 0; upLeftX &= binaryW upLeftX++)//从这一块当前行的第一格开始
//下面进行每格的对比,大数字去除的&块&是二维数组,小数组是一维数组
if (charArray[y + upLeftY][x + upLeftX] == charNum[upLeftY * (binaryWidth + 1) + upLeftX])
isIdentified = true;
//记录像素点是否比对成功
if (count == (binaryWidth + 1) * (binaryHeight + 1))//判断是否对比到了最后一个像素点
intStartXY[numIdentfied][0] =
//记录字库中该字符在图片中出现的Y值
intStartXY[numIdentfied][1] =
//记录字库中该字符在图片中出现的X值
//intStartXY[numIdentfied][2] = Convert.ToInt32(stringChar);
//将该字符转换为数字型
intStartXY[numIdentfied][2] = Integer.parseInt(stringChar+"");
//将该字符转换为数字型
numIdentfied++;
//记录图片中总共多少个字库中的数字
//一旦匹配即将结束比对
isIdentified = false;
//此像素点比对不成功
//如果该像素点值比对不成功即将结束比对
if (!isIdentified)//如果一个不符就向后退一格,同时小数组的比对又需要从第一格开始
//并且结束这次的比对
}catch(Exception e) { }
/// &summary&
/// 对比对后的结果通过坐标进行排序
/// &/summary&
/// &returns&提取出的图片中的字符串&/returns&
public String identifySort()
String stringLicense = "";
//存储该结果
int intTemp = 0;
for (int a = 0; a & numI a++)
{//从第一列开始
for (int b = 0; b & numI b++)
{//然后从该列中第一行开始对比
if (intStartXY[a][0] & intStartXY[b][0])
{//通过Y坐标(离顶端距离)判断那个字符在上面,并进行对调
for (int c = 0; c & 3; c++)
intTemp = intStartXY[a][c];
intStartXY[a][c] = intStartXY[b][c];
intStartXY[b][c] = intT
if (intStartXY[a][0] == intStartXY[b][0] && intStartXY[a][1] & intStartXY[b][1])
{//当Y坐标(离顶端距离)相同时,通过X坐标(离左端距离)判断那个字符在左面,并进行对调
for (int c = 0; c & 3; c++)
intTemp = intStartXY[a][c];
intStartXY[a][c] = intStartXY[b][c];
intStartXY[b][c] = intT
//------------------------下面是我需要的格式-------------------------------------------------------------
e4ebf340-563b5e1c-b04957df-baacc576
for (int h = 0; h & numI h++)
stringLicense += intStartXY[h][2];
if ((intStartXY[h + 1][0] == intStartXY[h][0] && intStartXY[h + 1][1] - intStartXY[h][ 1] &= 12
&& h & numIdentfied - 32))
stringLicense += "_";
//当同一行时,相差一个下划线距离就显示下划线_
if (intStartXY[h + 1][0] - intStartXY[h][0] &= 11 && h & numIdentfied - 17)
stringLicense += "\n";
//当不上一行时就输出\n
if (h == numIdentfied - 25 || h == numIdentfied - 17 || h == numIdentfied - 9)
stringLicense += "-";
//每8个显示一个中划线-
//---------------------------------------END---------------------------------------------------------------------------------
}catch(Exception ex){ }
return stringLicense + "\n";
//对返回的结果进行换行,保证在richTextBox文本框显示的时候光标始终在下行
阅读(...) 评论()

我要回帖

更多关于 摄像机通电没图像 的文章

 

随机推荐