我是android的初学者,在应用启动后一切正常,但我创建了一个文本识别应用程序,但是从相机捕获图像后,我无法在textview框中获取结果。
然后我检入logcat并在logcat中发现一些例外,并在
中带有蓝色下划线“ PROCESSIMAGE.JAVA:84,RECOGNIZETEXTACTIVITY.JAVA:161和 RECOGNIZETEXTACTIVITY:152“。
此后,我在google中找到了解决方案,但不幸的是我没有找到。
CvException [org.opencv.core.CvException: cv::Exception: /hdd2/buildbot/slaves/slave_ardbeg1/50-SDK/opencv/modules/core/src/matrix.cpp:323: error: (-215) 0 <= roi.x && 0 <= roi.width && roi.x + roi.width <= m.cols && 0 <= roi.y && 0 <= roi.height && roi.y + roi.height <= m.rows in function cv::Mat::Mat(const cv::Mat&, const Rect&)
]
at org.opencv.core.Mat.n_submat(Native Method)
at org.opencv.core.Mat.submat(Mat.java:2325)
at com.example.nabil.ocr.compa.readerocr.ProcessImage.parseBitmap(ProcessImage.java:84)
at com.example.nabil.ocr.compa.readerocr.RecognizeTextActivity.displayResult(RecognizeTextActivity.java:161)
at com.example.nabil.ocr.compa.readerocr.RecognizeTextActivity.onActivityResult(RecognizeTextActivity.java:152)
at android.app.Activity.dispatchActivityResult(Activity.java:7701)
at android.app.ActivityThread.deliverResults(ActivityThread.java:5031)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:5078)
at android.app.ActivityThread.-wrap20(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2053)
at android.os.Handler.dispatchMessage(Handler.java:108)
at android.os.Looper.loop(Looper.java:166)
at android.app.ActivityThread.main(ActivityThread.java:7523)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:245)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:921)
ProcessImage.java
public class ProcessImage {
static {
if (!OpenCVLoader.initDebug()) {
Log.w(TAG, "Unable to load OpenCV");
} else {
info("OpenCV loaded");
}
// For OCR
System.loadLibrary("gnustl_shared");
System.loadLibrary("nonfree");
}
public static boolean DEBUG = false; // Debug mode
public static String language = "eng";
public int sourceWidth = 1366; // To scale to
public static int thresholdMin = 85; // Threshold 80 to 105 is Ok
private int thresholdMax = 255; // Always 255
public String recognizeResult = "";
// Write debug image
private void writeImage(String name, Mat origin) {
if (!DEBUG) {
return;
}
String appPath = APP_PATH;
info("Writing " + appPath + name + "...");
imwrite(appPath + name, origin);
}
public boolean parseBitmap(Bitmap bitmap, int top, int bot, int right, int left) {
try {
Mat origin = new Mat();
Utils.bitmapToMat(bitmap, origin);
info("Mat size: " + origin.width() + ":" + origin.height());
// Crop image to get the resion inside the rectangle only
info("Crop T: " + top + " B: " + bot + " R: " + right + " L: " + left);
if (top != 0 && bot != 0 && right != 0 && left != 0) {
info("Cropping...");
origin = origin.submat(new Rect(right, top, left, bot));
writeImage("crop.jpg", origin);
}
boolean result = recognizeImage(origin);
origin.release();
return result;
} catch (Exception e) {
Log.e(TAG, "Error parse image. Message: " + e.getMessage(), e);
}
return false;
}
/**
*
* Parse image
*
* @Param origin
* @return
*/
private boolean recognizeImage(Mat origin) {
info("recognizeImage");
// Reset value
recognizeResult = "";
// Resize origin image
Size imgSize = origin.size();
resize(origin, origin, new Size(sourceWidth, imgSize.height * sourceWidth / imgSize.width), 1.0, 1.0,
INTER_CUBIC);
writeImage("resize.jpg", origin);
// Convert the image to GRAY
Mat originGray = new Mat();
cvtColor(origin, originGray, COLOR_BGR2GRAY);
// Process noisy, blur, and threshold to get black-white image
originGray = processNoisy(originGray);
writeImage("gray.jpg", originGray); // Black-White image
recognizeResult = matToString(originGray);
info("Done recognize");
originGray.release();
originGray = null;
info("Result: " + recognizeResult);
return true;
}
/**
* Crop sub mat by four points.
*
* @Param origin
* @Param tl
* @Param tr
* @Param bl
* @Param br
* @return
*/
private Mat cropSub(Mat origin, Point tl, Point tr, Point bl, Point br) {
info("cropSub");
int resultWidth = (int) (tr.x - tl.x);
int bottomWidth = (int) (br.x - bl.x);
if (bottomWidth > resultWidth)
resultWidth = bottomWidth;
int resultHeight = (int) (bl.y - tl.y);
int bottomHeight = (int) (br.y - tr.y);
if (bottomHeight > resultHeight)
resultHeight = bottomHeight;
List<Point> source = new ArrayList<Point>();
source.add(tl);
source.add(tr);
source.add(bl);
source.add(br);
Mat startM = Converters.vector_Point2f_to_Mat(source);
Point outTL = new Point(0, 0);
Point outTR = new Point(resultWidth, 0);
Point outBL = new Point(0, resultHeight);
Point outBR = new Point(resultWidth, resultHeight);
List<Point> dest = new ArrayList<Point>();
dest.add(outTL);
dest.add(outTR);
dest.add(outBL);
dest.add(outBR);
Mat endM = Converters.vector_Point2f_to_Mat(dest);
Mat subTrans = getPerspectiveTransform(startM, endM);
Mat subMat = new Mat();
warpPerspective(origin, subMat, subTrans, new Size(resultWidth, resultHeight));
subTrans.release();
return subMat;
}
/**
* Process noisy or blur image with simplest filters
* @Param grayMat
* @return
*/
private Mat processNoisy(Mat grayMat) {
Mat element1 = getStructuringElement(MORPH_RECT, new Size(2, 2), new Point(1, 1));
Mat element2 = getStructuringElement(MORPH_RECT, new Size(2, 2), new Point(1, 1));
dilate(grayMat, grayMat, element1);
erode(grayMat, grayMat, element2);
GaussianBlur(grayMat, grayMat, new Size(3, 3), 0);
// The thresold value will be used here
threshold(grayMat, grayMat, thresholdMin, thresholdMax, THRESH_BINARY);
return grayMat;
}
/**
* Convert mat to string
*
* @Param source
* @return
*/
private String matToString(Mat source) {
int newWidth = source.width()/2;
resize(source, source, new Size(newWidth, (source.height() * newWidth) / source.width()));
writeImage("text.jpg", source);
CharDetectOCR ocrReader = new CharDetectOCR();
String result = ocrReader.getOCRResult(toBitmap(source));
//result = result.replace("O", "0"); // Replace O to 0 if have.
return result;
}
/**
* Convert mat to bitmap
*
* @Param mat
* @return
*/
public static Bitmap toBitmap(Mat mat) {
Bitmap bitmap = Bitmap.createBitmap(mat.width(), mat.height(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(mat, bitmap);
return bitmap;
}
}
RecognizeTextActivity.Java
public class RecognizeTextActivity extends Activity { static int REQUEST_IMAGE_CAPTURE = 1; static ProcessImage processImg = new ProcessImage();
Button btnStartCamera;
Button btnExit;
private String language;
private TouchImageView image;
private EditText recognizeResult;
private int sourceW = 0;
private int sourceH = 0;
private String lastFileName = "";
private boolean isRecognized = false;
ProgressDialog progressBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_reader);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
Bundle b = getIntent().getExtras();
language = b.getString("language");
ProcessImage.language = language;
ProcessImage.thresholdMin = Integer.parseInt(b.getString("threshold"));
info("Language: "+ language + " threshold: "+ ProcessImage.thresholdMin);
btnStartCamera = (Button) findViewById(R.id.btnStartCamera);
btnExit = (Button) findViewById(R.id.btnExit);
btnStartCamera.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View arg0, MotionEvent arg1) {
if (arg1.getAction() == MotionEvent.ACTION_UP) {
takePicture();
}
return false;
}
});
btnExit.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View arg0, MotionEvent arg1) {
if (arg1.getAction() == MotionEvent.ACTION_UP) {
existApp();
}
return false;
}
});
recognizeResult = (EditText) findViewById(R.id.recognize_result);
image = (TouchImageView) findViewById(R.id.grid_img);
image.setScaleType(ScaleType.CENTER_INSIDE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
new InitTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} else {
new InitTask().execute();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.recognize, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
private void takePicture() {
Intent takePicIntent = new Intent(RecognizeTextActivity.this, AndroidCamera.class);
lastFileName = CommonUtils.APP_PATH + "capture" + System.currentTimeMillis() + ".jpg";
takePicIntent.putExtra("output", lastFileName);
info(lastFileName);
startActivityForResult(takePicIntent, REQUEST_IMAGE_CAPTURE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
BitmapFactory.Options options = new BitmapFactory.Options();
Bitmap imageBitmap = BitmapFactory.decodeFile(lastFileName, options);
if (imageBitmap == null) {
// Try again
isRecognized = false;
image.setImageBitmap(imageBitmap);
hideProcessBar();
dialogBox("Can not recognize sheet. Please try again", "Retry", "Exist", true);
return;
}
final Bitmap finalImageBitmap = imageBitmap.getWidth() > imageBitmap.getHeight()
? rotateBitmap(imageBitmap, 90) : imageBitmap;
int top = data.getIntExtra("top", 0);
int bot = data.getIntExtra("bot", 0);
int right = data.getIntExtra("right", 0);
int left = data.getIntExtra("left", 0);
image.setImageBitmap(finalImageBitmap);
displayResult(finalImageBitmap, top, bot, right, left);
}
}
public void displayResult(Bitmap imageBitmap, int top, int bot, int right, int left) {
info("Origin size: " + imageBitmap.getWidth() + ":" + imageBitmap.getHeight());
// Parser
recognizeResult.setText("");
if (processImg.parseBitmap(imageBitmap, top, bot, right, left)) {
// TODO: set result
recognizeResult.setText(processImg.recognizeResult);
// TODO: write result to image
// image.setImageBitmap(toBitmap(processImg.drawAnswered(numberAnswer)));
isRecognized = true;
hideProcessBar();
} else {
// Try again
isRecognized = false;
image.setImageBitmap(imageBitmap);
hideProcessBar();
dialogBox("Can not recognize sheet. Please try again", "Retry", "Exist", true);
}
}
public Bitmap rotateBitmap(Bitmap source, float angle) {
Matrix matrix = new Matrix();
matrix.postRotate(angle);
return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true);
}
public void dialogBox(String message, String bt1, String bt2, final boolean flagContinue) {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
alertDialogBuilder.setMessage(message);
alertDialogBuilder.setPositiveButton(bt1, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface arg0, int arg1) {
if (flagContinue) {
takePicture();
}
}
});
if (bt2 != "") {
alertDialogBuilder.setNegativeButton(bt2, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface arg0, int arg1) {
existApp();
// return false;
}
});
}
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
}
public void existApp() {
CommonUtils.cleanFolder();
this.finish();
}
public void showProgressBar(String title, String message) {
progressBar = ProgressDialog.show(this, title, message, false, false);
}
public void hideProcessBar() {
runOnUiThread(new Runnable() {
@Override
public void run() {
if (progressBar != null && progressBar.isShowing()) {
progressBar.dismiss();
}
}
});
}
private class InitTask extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... data) {
try {
CharDetectOCR.init(getAssets());
return "";
} catch (Exception e) {
Log.e("COMPA", "Error init data OCR. Message: " + e.getMessage());
}
return "";
}
@Override
protected void onPostExecute(String result) {
}
}
}