마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

Fatal signal 11 (SIGSEGV), code 1, fault addr 0x9b3ffffa in tid 2045 (AsyncTask #3)

0 추천
안녕하세요.
 

android opencv library를 사용하여 image를 crop하고 있습니다.

어떤 디바이스에서는 이런 이슈가 나오는데 이 이슈에 대한 정보를 아시는 분은

이슈에 대한 정보와 해결책을 알려주시면 감사하겠습니다.

아래는 해당 소스입니다.

File fileFolio = new File(bmpFilePath);
String filePath = fileFolio.getParent();

/**원본 Bitmap 이미지 흑백 이미지로 불러오기*/
Log.d(TAG, "deskew crop scannedBmpFilePath: " + bmpFilePath);
Mat matOriginal = Imgcodecs.imread(bmpFilePath, Imgcodecs.IMREAD_GRAYSCALE);
Log.d(TAG, "deskew crop imread complete");

/**흑백 Bitmap 이미지를 Png 이미지로 저장*/
Log.d(TAG, "deskew crop show image");

matResult = matOriginal.clone();
matOriginal.release();

// crop 기능 시작
Log.d(TAG, "Image Crop start");

File pngOriginal = new File(filePath, fileFolio.getName() + "_grayscaled.png");
pngResult = pngOriginal.getAbsolutePath();

matRgb = new Mat();
Imgproc.cvtColor(matOriginal, matRgb, Imgproc.COLOR_GRAY2RGB);
Imgcodecs.imwrite(pngResult, matRgb);
matRgb.release();
    /*Crop 영역 얻어오기*/
int[] aryRectContent = HelperImageProcess.findCropBoundary(matResult.getNativeObjAddr());
int x = aryRectContent[0];
int y = aryRectContent[1];
int width = aryRectContent[2];
int height = aryRectContent[3];
Rect roi = new Rect(x, y, width, height);
HelperImageProcess.findCropBoundary(matResult.getNativeObjAddr());

위 코드에서 이슈가 나는 것 같습니다.

아래는 위 코드의 소스입니다.

Mat &matInput = *(Mat *) matAddrInput;         // OpenCV에서 사용하는 이미지 객체 (grayscale로 변환 된 이미지일 것)
    LOGD(LOG_TAG, "matInput channels: %d", matInput.channels());
    LOGD(LOG_TAG, "matInput channels: %d", matInput.rows);
    LOGD(LOG_TAG, "matInput channels: %d", matInput.cols);

    int i, x, y, z;         // Loop 인덱스
    int iCutThreshold = 80; // 바탕에 밝은 영역이 많을 수록 값을 증가 시키도록 한다. 실제 이미지를 통해 조절하도록!
    bool bFlag;             // 중첩 Loop 탈출 플래그
    int Offset = 2;         // 상하좌우 순회 시작 위치를 약간 띄고 시작. 노이즈로 인해 최외곽 영역에 흰 줄이 가는 경우 대비.
    int iBundle = 10;
    int iCount;

    // 이미지 최대 외곽 영역에서 최소 영역으로 점차 좁혀갈 최종 영역
    int rcCrop_top = 0;
    int rcCrop_bottom = matInput.rows - 1;
    int rcCrop_left = 0;
    int rcCrop_right = matInput.cols;

    // FIXME: 만일 skew 가 반시계 방향이었다면 좌측 상단은 잘려있을 수 있으므로, deskew 후에 안잘린 우측에서 좌측으로 순회하자. 같은 이유로 상하좌우 4 방향으로 영역 좁힐 때 모두가 마찬가지.
    // TODO: Crop 이후에 잘려있던 검은 영역을 흰색으로 채워줄 지는 논의 필요.

    // top
    bFlag = false;
    for (y = Offset; y < matInput.rows - Offset; y++) {
        for (x = Offset; x < matInput.cols - Offset; x += 4) {
            if (matInput.at<uchar>(y, x) > iCutThreshold) {
                iCount = 0;
                for (z = 0; z < iBundle; z++) {
                    if (matInput.at<uchar>(y + z, x + z) > iCutThreshold) iCount++;
                }
                if (iCount == iBundle) {
                    rcCrop_top = y;
                    bFlag = true;
                    break;
                }
            }
        }
        if (bFlag) break;
    }

    // bottom
    bFlag = false;
    for (y = matInput.rows - 1 - Offset; y >= Offset; y--) {
        for (x = Offset; x < matInput.cols - Offset; x += 4) {
            if (matInput.at<uchar>(y, x) > iCutThreshold) {
                iCount = 0;
                for (z = 0; z < iBundle; z++) {
                    if (matInput.at<uchar>(y - z, x + z) > iCutThreshold) iCount++;
                }
                if (iCount == iBundle) {
                    rcCrop_bottom = y;
                    bFlag = true;
                    break;
                }
            }
        }
        if (bFlag) break;
    }

    // left
    bFlag = false;
    for (x = Offset; x < matInput.cols - Offset; x++) {
        for (y = Offset; y < matInput.rows - Offset; y += 4) {
            if (matInput.at<uchar>(y, x) > iCutThreshold) {
                iCount = 0;
                for (z = 0; z < iBundle; z++) {
                    if (matInput.at<uchar>(y + z, x + z) > iCutThreshold) iCount++;
                }
                if (iCount == iBundle) {
                    rcCrop_left = x;
                    bFlag = true;
                    break;
                }
            }
        }
        if (bFlag) break;
    }

    // right
    bFlag = false;
    for (x = matInput.cols - 1 - Offset; x >= Offset; x--) {
        for (y = Offset; y < matInput.rows - Offset; y += 4) {
            if (matInput.at<uchar>(y, x) > iCutThreshold) {
                iCount = 0;
                for (z = 0; z < iBundle; z++) {
                    if (matInput.at<uchar>(y - z, x - z) > iCutThreshold) iCount++;
                }
                if (iCount == iBundle) {
                    rcCrop_right = x;
                    bFlag = true;
                    break;
                }
            }
        }
        if (bFlag) break;
    }

    // C++ opencv CvRect 와 Java opencv Rect 쌍을 맞추어 반환
    CvRect rect(rcCrop_left, rcCrop_top, rcCrop_right - rcCrop_left, rcCrop_bottom - rcCrop_top);

    // 상하좌우 픽셀 인덱스를 보관할 자바 정수형 배열 생성
    jintArray intArray = env->NewIntArray(4);

    // C 배열 포인터를 이용하여 자바 정수형 배열을 설정 (순서 주의! Java 코드와 맞추어야 함. x, y, width, height)
    jint *ptrArray = env->GetIntArrayElements(intArray, nullptr);
    ptrArray[0] = rect.x;
    ptrArray[1] = rect.y;
    ptrArray[2] = rect.width;
    ptrArray[3] = rect.height;

    // C 배열 포인터 해제
    env->ReleaseIntArrayElements(intArray, ptrArray, 0);

    // 자바 정수형 배열 반환
    return intArray;

아래는 해당 로그입니다.

08-31 18:02:31.977 1889-2045/kr.co.mirusystems.rts A/libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0x9b3ffffa in tid 2045 (AsyncTask #3)

08-31 18:02:32.032 124-124/? I/DEBUG: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
08-31 18:02:32.032 124-124/? I/DEBUG: Build fingerprint: 'Android/aosp_s5p6818_drone/s5p6818_drone:5.1.1/LMY48G/root11101821:userdebug/test-keys'
08-31 18:02:32.032 124-124/? I/DEBUG: Revision: '0'
08-31 18:02:32.032 124-124/? I/DEBUG: ABI: 'arm'
08-31 18:02:32.033 124-124/? I/DEBUG: pid: 1889, tid: 2045, name: AsyncTask #3  >>> kr.co.mirusystems.rts <<<
08-31 18:02:32.033 124-124/? I/DEBUG: signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x9b3ffffa
08-31 18:02:32.071 124-124/? I/DEBUG:     r0 9b3ffffa  r1 00000a1a  r2 ffffffff  r3 00000a1a
08-31 18:02:32.072 124-124/? I/DEBUG:     r4 a2b2330c  r5 af4b72e0  r6 89805f0c  r7 a2b232e8
08-31 18:02:32.072 124-124/? I/DEBUG:     r8 a2b23390  r9 b4b07400  sl a2b23310  fp b4b07400
08-31 18:02:32.072 124-124/? I/DEBUG:     ip ffffffff  sp a2b23230  lr af466078  pc a37ff458  cpsr 200f0030
08-31 18:02:32.072 124-124/? I/DEBUG: backtrace:
08-31 18:02:32.072 124-124/? I/DEBUG:     #00 pc 00002458  /data/app/kr.co.mirusystems.rts-1/lib/arm/libdeskewcrop-lib.so (Java_kr_co_mirusystems_deskewcrop_helper_HelperImageProcess_findCropBoundary+839)
08-31 18:02:32.072 124-124/? I/DEBUG:     #01 pc 000a2d81  /system/lib/libart.so (art_quick_generic_jni_trampoline+32)
08-31 18:02:32.072 124-124/? I/DEBUG:     #02 pc 000a989c  /dev/ashmem/dalvik-non moving space (deleted)
08-31 18:02:33.680 124-124/? I/DEBUG: Tombstone written to: /data/tombstones/tombstone_00
익명사용자 님이 2018년 3월 1일 질문
2018년 3월 1일 수정
SEGV_MAPERR라는 로그가 있는게, 잘 못된 메모리를 엑서스 한듯 합니다.
matResult.getNativeObjAddr() 로 메모리 주소를 넘겨주는듯 한데, int인지 long이 확인 해 보세요. 64bit 단말에선 int로 입력될 경우 제 주소를 못 찾을 수 있습니다.

long인데도 발생한다면,
c쪽
 Java_kr_co_mirusystems_deskewcrop_helper_HelperImageProcess_findCropBoundary  메소드에 로그를 계속 넣으면서, 어느 시점에서 문제가 되었는지 찾으셔야 할 듯 합니다.

답변 달기

· 글에 소스 코드 보기 좋게 넣는 법
· 질문에 대해 추가적인 질문이나 의견이 있으면 답변이 아니라 댓글로 달아주시기 바랍니다.
표시할 이름 (옵션):
개인정보: 당신의 이메일은 이 알림을 보내는데만 사용됩니다.
스팸 차단 검사:
스팸 검사를 다시 받지 않으려면 로그인하거나 혹은 가입 하세요.
...