나는 하루 종일 해결책을 찾고 있습니다. 내 문제와 관련하여 여러 스레드를 확인했습니다.
- 맞춤형 검출기 개체
- 바코드 추적 창 감소
- 그리고 더…
그러나 그것은별로 도움이되지 않았습니다. 기본적으로 카메라 미리보기는 전체 화면이지만 텍스트는 사각형이 그려지는 화면 중앙에서만 인식됩니다.
내가 사용하는 기술 :
- 광학 문자 인식 (OCR)을위한 Google 모바일 비전 API
- 의존성 :
play-services-vision
내 현재 상태 : BoxDetector 클래스를 만들었습니다.
public class BoxDetector extends Detector {
private Detector mDelegate;
private int mBoxWidth, mBoxHeight;
public BoxDetector(Detector delegate, int boxWidth, int boxHeight) {
mDelegate = delegate;
mBoxWidth = boxWidth;
mBoxHeight = boxHeight;
}
public SparseArray detect(Frame frame) {
int width = frame.getMetadata().getWidth();
int height = frame.getMetadata().getHeight();
int right = (width / 2) + (mBoxHeight / 2);
int left = (width / 2) - (mBoxHeight / 2);
int bottom = (height / 2) + (mBoxWidth / 2);
int top = (height / 2) - (mBoxWidth / 2);
YuvImage yuvImage = new YuvImage(frame.getGrayscaleImageData().array(), ImageFormat.NV21, width, height, null);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
yuvImage.compressToJpeg(new Rect(left, top, right, bottom), 100, byteArrayOutputStream);
byte[] jpegArray = byteArrayOutputStream.toByteArray();
Bitmap bitmap = BitmapFactory.decodeByteArray(jpegArray, 0, jpegArray.length);
Frame croppedFrame =
new Frame.Builder()
.setBitmap(bitmap)
.setRotation(frame.getMetadata().getRotation())
.build();
return mDelegate.detect(croppedFrame);
}
public boolean isOperational() {
return mDelegate.isOperational();
}
public boolean setFocus(int id) {
return mDelegate.setFocus(id);
}
@Override
public void receiveFrame(Frame frame) {
mDelegate.receiveFrame(frame);
}
}
그리고이 클래스의 인스턴스를 여기에 구현했습니다.
final TextRecognizer textRecognizer = new TextRecognizer.Builder(App.getContext()).build();
// Instantiate the created box detector in order to limit the Text Detector scan area
BoxDetector boxDetector = new BoxDetector(textRecognizer, width, height);
//Set the TextRecognizer's Processor but using the box collider
boxDetector.setProcessor(new Detector.Processor<TextBlock>() {
@Override
public void release() {
}
/*
Detect all the text from camera using TextBlock
and the values into a stringBuilder which will then be set to the textView.
*/
@Override
public void receiveDetections(Detector.Detections<TextBlock> detections) {
final SparseArray<TextBlock> items = detections.getDetectedItems();
if (items.size() != 0) {
mTextView.post(new Runnable() {
@Override
public void run() {
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < items.size(); i++) {
TextBlock item = items.valueAt(i);
stringBuilder.append(item.getValue());
stringBuilder.append("\n");
}
mTextView.setText(stringBuilder.toString());
}
});
}
}
});
mCameraSource = new CameraSource.Builder(App.getContext(), boxDetector)
.setFacing(CameraSource.CAMERA_FACING_BACK)
.setRequestedPreviewSize(height, width)
.setAutoFocusEnabled(true)
.setRequestedFps(15.0f)
.build();
실행시이 예외가 발생합니다.
Exception thrown from receiver.
java.lang.IllegalStateException: Detector processor must first be set with setProcessor in order to receive detection results.
at com.google.android.gms.vision.Detector.receiveFrame(com.google.android.gms:play-services-vision-common@@19.0.0:17)
at com.spectures.shopendings.Helpers.BoxDetector.receiveFrame(BoxDetector.java:62)
at com.google.android.gms.vision.CameraSource$zzb.run(com.google.android.gms:play-services-vision-common@@19.0.0:47)
at java.lang.Thread.run(Thread.java:919)
누군가 단서가 있거나 내 잘못이 무엇인지 또는 대안이 있다면 정말 감사하겠습니다. 감사합니다!
이것이 내가 달성하고자하는 것입니다. 텍스트 영역 스캐너 :
답변
구글 비전 감지는 입력 프레임입니다. 프레임은 이미지 데이터이며 관련 데이터로 너비와 높이를 포함합니다. U는이 프레임을 검출기로 전달하기 전에 처리 할 수 있습니다 (작은 중앙 프레임으로 자릅니다). 이 과정은 빠르고 카메라 처리 이미지와 함께 수행되어야합니다. 아래에서 내 Github을 확인하십시오 (FrameProcessingRunnable 검색). U는 프레임 입력을 볼 수 있습니다. 당신은 거기에서 스스로 프로세스를 수행 할 수 있습니다.
답변
google-vision에서는 Mobile Vision API를 사용하여 이미지에서 텍스트 위치를 얻는 방법에 설명 된 것처럼 감지 된 텍스트의 좌표를 얻을 수 있습니다 .
당신은 얻을 TextBlocks
에서 TextRecognizer
당신은을 필터링 TextBlock
에 의해 결정될 수있다 자신의 좌표에 의해 getBoundingBox()
또는 getCornerPoints()
방법 TextBlocks
클래스 :
텍스트 인식기
인식 결과는 detect (Frame)에 의해 반환됩니다. OCR 알고리즘은 텍스트 레이아웃을 유추하려고 시도하고 각 단락을 TextBlock 인스턴스로 구성합니다. 텍스트가 감지되면 하나 이상의 TextBlock 인스턴스가 반환됩니다.
[..]
공개 방법
public SparseArray<TextBlock> detect (Frame frame)
이미지의 텍스트를 감지하고 인식합니다. 현재 비트 맵 및 NV21 만 지원합니다. int 도메인에 텍스트 블록의 불투명 한 ID를 나타내는 int를 TextBlock에 매핑합니다.
출처 : https://developers.google.com/android/reference/com/google/android/gms/vision/text/TextRecognizer
TextBlock
public class TextBlock extends Object implements Text
OCR 엔진에 의해 간주되는 텍스트 블록 (문단으로 생각)
공개 메소드 요약
Rect getBoundingBox()
TextBlock의 축 정렬 경계 상자를 반환합니다.
List<? extends Text> getComponents()
이 엔티티를 구성하는 더 작은 구성 요소 (있는 경우).
Point[] getCornerPoints()
왼쪽 상단부터 시작하여 시계 방향으로 4 개의 모서리 지점.
String getLanguage()
TextBlock에서 통용되는 언어.
String getValue()
인식 된 텍스트를 문자열로 검색하십시오.
출처 : https://developers.google.com/android/reference/com/google/android/gms/vision/text/TextBlock
따라서 기본적으로 Mobile Vision API를 사용하여 이미지에서 텍스트 위치를 얻는 방법에서 와 같이 진행하십시오 . 그러나 당신은 한 줄로 블록을 나누지 않고 다음과 같은 단어로 줄을 나눕니다.
//Loop through each `Block`
foreach (TextBlock textBlock in blocks)
{
IList<IText> textLines = textBlock.Components;
//loop Through each `Line`
foreach (IText currentLine in textLines)
{
IList<IText> words = currentLine.Components;
//Loop through each `Word`
foreach (IText currentword in words)
{
//Get the Rectangle/boundingBox of the word
RectF rect = new RectF(currentword.BoundingBox);
rectPaint.Color = Color.Black;
//Finally Draw Rectangle/boundingBox around word
canvas.DrawRect(rect, rectPaint);
//Set image to the `View`
imgView.SetImageDrawable(new BitmapDrawable(Resources, tempBitmap));
}
}
}
대신 당신은 얻을 경계 상자 의 모든 텍스트 블록을 다음 화면 / 프레임의 중앙 또는 사용자가 지정하는 사각형에 가장 가까운 좌표와 경계 상자를 선택 (즉, 내가 중심 X를 얻을 수있는 방법, 안드로이드에서 내보기의 Y? ) 이를 위해 getBoundingBox()
또는 getCornerPoints()
방법 을 사용합니다 TextBlocks
…