상세 컨텐츠

본문 제목

Cannot copy to a TensorFlowLite tensor (serving_default_sequential_1_input:0) with 602112 bytes from a Java Buffer with 200704 bytes.

AI

by cepiloth 2022. 1. 10. 13:58

본문

728x90
반응형

추론하려고 하는 모델의 인풋 속성이 INPUT 이미지에 속성이 224 x 224 x 3 크기로 사용했어야 하는데 모델 정보를 확인 안 하고 추론을 진행하였다. 오류 내용처럼 602112 바이트의 크기로 ByteBuffer를 만들어야 했었는 에 아래 코드는 224 x 224 * 1 의 크기로 ByteBuffer를 만들어서 전달하였다.

    private ByteBuffer convertBitmapToGrayByteBuffer(Bitmap bitmap) {
        ByteBuffer byteByffer = ByteBuffer.allocateDirect(bitmap.getByteCount());
        byteByffer.order(ByteOrder.nativeOrder());

        int[] pixels = new int[bitmap.getWidth() * bitmap.getHeight()];
        bitmap.getPixels(pixels, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());

        for (int pixel : pixels) {
            int r = pixel >> 16 & 0xFF;
            int g = pixel >> 8 & 0xFF;
            int b = pixel & 0xFF;

            float avgPixelValue = (r + g + b) / 3.0f;
            float normalizedPixelValue = avgPixelValue / 255.0f;

            byteByffer.putFloat(normalizedPixelValue);
        }

        return byteByffer;
    }

 

스택오버플로우에 검색해보니 아래와 같은 설명이 있다. 

이것은 모델의 INPUT 불일치로 인해 발생합니다. 모델 설명에 따르면 정수형 입력/출력, 아마도 양자화된 모델이 있습니다. 공급할 부동 소수점 데이터 버퍼를 준비하려고 합니다. 가장 일반적인 2가지 설루션이 있습니다. 

1) uint8 데이터를 준비합니다. 비트맵 픽셀을 1바이트 uint8s로 바이트 버퍼를 사용한다.
2) 부동 소수점 입력이 있는 모델을 찾고 코드 사용

imgData = ByteBuffer.allocateDirect(DIM_BATCH_SIZE * DIM_IMG_SIZE_X * DIM_IMG_SIZE_Y * DIM_PIXEL_SIZE); // now buffer size and input size match

imgData.order(ByteOrder.nativeOrder());

Bitmap reshapeBitmap = Bitmap.createScaledBitmap(bitmap, 224, 224, false);
convertBitmapToByteBuffer(reshapeBitmap);


private void convertBitmapToByteBuffer(Bitmap bitmap) {
        if (imgData == null) {
            return;
        }
        imgData.rewind();
        bitmap.getPixels(intValues, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());
        // Convert the image to floating point.
        int pixel = 0;
        long startTime = SystemClock.uptimeMillis();
        for (int i = 0; i < DIM_IMG_SIZE_X; ++i) {
            for (int j = 0; j < DIM_IMG_SIZE_Y; ++j) {
                final int val = intValues[pixel++];
                imgData.putChar((byte)((((val >> 16) & 0xFF)-IMAGE_MEAN)/IMAGE_STD*255));
                imgData.putChar((byte)((((val >> 8) & 0xFF)-IMAGE_MEAN)/IMAGE_STD*255));
                imgData.putChar((byte)((((val) & 0xFF)-IMAGE_MEAN)/IMAGE_STD*255));
            }
        }
        long endTime = SystemClock.uptimeMillis();
        //Log.d("Timecost to put values into ByteBuffer: " + Long.toString(endTime - startTime));
    }

 

혹시 누군가 비슷한 문제를 겪을지 몰라 포스팅을 남긴다. TensorFlow Lite에서 모델을 추론할 때 모델의 INPUT 사이즈를 꼭 확인하고 처리해야 한다. 안드로이드 스튜디오에서 tflite 모델 파일을 클릭하면 모델정보를 알 수 있다. 하지만 모델을 만든 개발자가 메타데이터를 입력을 하지 않으면 아래 처럼 모델에 대한 정보를 알 수 없다. 메타데이터를 넣어 주는 것이 추후에 디버깅하거나 모델을 사용할때 유추하게 편할거같다.

 

메타데이터를 알 수 없을 때는 Tensor 를 통하여 모델 정보를 확인 할 수 있다. 

    public Classifier(Context context) {
        this.context = context;
    }

    // 1. 모델 로드 하는 코드(1)
    public void init() throws IOException {
        ByteBuffer model = loadModelFile(MODEL_NAME);
        model.order(ByteOrder.nativeOrder());
        interpreter = new Interpreter(model);

        initModelShape();
    }
    // 2. 모델 로드 하는 코드(2)
    private ByteBuffer loadModelFile(String modelName) throws IOException {
        AssetManager am = context.getAssets();
        AssetFileDescriptor afd = am.openFd(modelName);
        FileInputStream fis = new FileInputStream(afd.getFileDescriptor());
        FileChannel fc = fis.getChannel();
        long startOffset = afd.getStartOffset();
        long declaredLength = afd.getDeclaredLength();

        return fc.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength);
    }

    // 3. interpreter를 통하여 0 번째 인덱스의 Tensor 를 가져오는 코드
    private void initModelShape() {
        Tensor inputTensor = interpreter.getInputTensor(0);
        int[] inputShape = inputTensor.shape();
        modelInputChannel = inputShape[0];
        modelInputWidth = inputShape[1];
        modelInputHeight = inputShape[2];

        Tensor outputTensor = interpreter.getOutputTensor(0);
        int[] outputShape = outputTensor.shape();
        modelOutputClasses = outputShape[1];
    }

모델을 로드하고 getInputTensor(0) 0 은 index 첫번째 층의 tensor 를 가져 온다. 아래처럼 inputShape 을 확인 추론하려는 모델의 입력정보를 확인 할 수 있다. 

 

Reference

https://stackoverflow.com/questions/67419320/cannot-copy-to-a-tensorflowlite-tensor-input-1-with-150528-bytes-from-a-java-b

 

Cannot copy to a TensorFlowLite tensor (input_1) with 150528 bytes from a Java Buffer with 602112 bytes

I'm trying to use my model in the tflitecamerademo example. Here is my model The demo crashes with the following reason java.lang.IllegalArgumentException: Cannot copy to a TensorFlowLite tensor (

stackoverflow.com

https://www.tensorflow.org/lite/api_docs/java/org/tensorflow/lite/Interpreter

 

Interpreter  |  TensorFlow Lite

도움말 Kaggle에 TensorFlow과 그레이트 배리어 리프 (Great Barrier Reef)를 보호하기 도전에 참여 이 페이지는 Cloud Translation API를 통해 번역되었습니다. Switch to English Interpreter TensorFlow Lite로 모델 추론을

www.tensorflow.org

 

728x90
반응형

관련글 더보기

댓글 영역