ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Android NDK + OpenCV 관심영역(ROI)에 영상처리하는 예제
    OpenCV/Android 개발 환경 및 예제 2019.05.13 19:08

     

    카메라로부터 캡처된 영상에  관심영역(ROI)을 지정하여 영상처리 하는 예제입니다.  

    위치는 텍스트로된 코드에서 확인하고 코드 복사는 코드블록에 있는 것을 사용하세요. 



    업데이트

    2019. 5. 11

     

     

    유튜브 영상 또는 아래 글을 보고 진행하세요.

     

     

     

    아래 포스팅 진행한 후 필요한 부분을 추가해서 완성합니다.

     

    Android NDK + OpenCV 카메라 예제 및 프로젝트 생성방법(CMake 사용)

    https://webnautes.tistory.com/1054




    추가 1 : MainActivity.java

     

    public class MainActivity extends AppCompatActivity

           implements CameraBridgeViewBase.CvCameraViewListener2, View.OnTouchListener {

    public class MainActivity extends AppCompatActivity
    
           implements CameraBridgeViewBase.CvCameraViewListener2, View.OnTouchListener {




    추가 2 : MainActivity.java

     

       private Mat matInput;

       private Mat matResult;

       private Mat matInput1, matInput2;

       private Mat matMask=null, matNotMask=null;

       Rect rect = new Rect();

       private int step = -1;

       private Mat matInput1, matInput2;
       private Mat matMask=null, matNotMask=null;
       Rect rect = new Rect();
       private int step = -1;



    추가 3 : MainActivity.java

     

       @Override

       protected void onCreate(Bundle savedInstanceState) {

           . . . . . . . . . . . . . .  . . . . .

           mOpenCvCameraView.setOnTouchListener(this);

    mOpenCvCameraView.setOnTouchListener(this);



    추가 4 : MainActivity.java

     

       @Override

       public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {

     

           matInput = inputFrame.rgba();



           if ( matResult == null )

               matResult = new Mat(matInput.rows(), matInput.cols(), matInput.type());

     

           if ( matInput1 == null )

               matInput1 = new Mat(matInput.rows(), matInput.cols(), matInput.type());

     

           if ( matInput2 == null )

               matInput2 = new Mat(matInput.rows(), matInput.cols(), matInput.type());

     

           if ( matNotMask == null )

               matNotMask = new Mat(matInput.rows(), matInput.cols(), matInput.type());



           if ( step == 1){

               Imgproc.circle(matInput, new Point(rect.x, rect.y),  20, new Scalar(0, 255, 0, 255), -1);

               return matInput;

     

           }else if (step == 2){

     

               if (matMask != null ) {

                   Core.bitwise_and(matInput, matMask, matInput1);

                   ConvertRGBtoGray(matInput1.getNativeObjAddr(), matInput1.getNativeObjAddr());

     

                   if ( matMask == null || matNotMask == null ){

                       return matInput;

                   }

     

                   Core.bitwise_not(matMask, matNotMask);

                   Core.bitwise_and(matInput, matNotMask, matInput2);

     

                   Imgproc.cvtColor(matInput1, matInput1, Imgproc.COLOR_GRAY2RGBA);

     

                   Core.bitwise_or(matInput1, matInput2, matResult);

     

                   return matResult;

               }

     

           }

     

           return matInput;

       }

           if ( matInput1 == null )
               matInput1 = new Mat(matInput.rows(), matInput.cols(), matInput.type());
    
           if ( matInput2 == null )
               matInput2 = new Mat(matInput.rows(), matInput.cols(), matInput.type());
    
           if ( matNotMask == null )
               matNotMask = new Mat(matInput.rows(), matInput.cols(), matInput.type());
    
    
           if ( step == 1){
    
               Imgproc.circle(matInput, new Point(rect.x, rect.y),  20, new Scalar(0, 255, 0, 255), -1);
               return matInput;
    
           }else if (step == 2){
    
               if (matMask != null ) {
                   Core.bitwise_and(matInput, matMask, matInput1);
                   ConvertRGBtoGray(matInput1.getNativeObjAddr(), matInput1.getNativeObjAddr());
    
                   if ( matMask == null || matNotMask == null ){
                       return matInput;
                   }
    
                   Core.bitwise_not(matMask, matNotMask);
                   Core.bitwise_and(matInput, matNotMask, matInput2);
                   Imgproc.cvtColor(matInput1, matInput1, Imgproc.COLOR_GRAY2RGBA);
                   Core.bitwise_or(matInput1, matInput2, matResult);
    
                   return matResult;
               }
    
           }
    
           return matInput;
    
       }




    추가 5 : MainActivity.java

     

         @Override

       public boolean onTouch (View v, MotionEvent event){



           int width = matInput.cols();

           int height = matInput.rows();



           // 카메라 뷰와 이미지 좌표 맞추기

           int xOffset = (mOpenCvCameraView.getWidth() - width) / 2;

           int yOffset = (mOpenCvCameraView.getHeight() - height) / 2;

     

           int x = (int) event.getX() - xOffset;

           int y = (int) event.getY() - yOffset;



           if (x < 0 || y < 0 || x >= width || y >= height) {// 터치가 범위 벗어난 경우

     

               step = -1;

               rect.x = rect.y = rect.width = rect.height = 0;

               matMask = null;

               return false;

           }



           if ( step == 2) { // ROI 설정된 상태에서 또 터치하면 설정 취소

               step = -1;

               rect.x = rect.y = rect.width = rect.height = 0;

               matMask = null;

               return false;

           }



           if ((step == -1)&&((rect.x == 0 && rect.y == 0) || (rect.width != 0 && rect.height != 0))) { //첫번째 클릭

     

               step = 1;

               matMask = null;

               rect.x = x;

               rect.y = y;

               rect.width = rect.height = 0;

     

           } else if ( step == 1){  //두번째 클릭

     

               rect.width = x - rect.x;

               rect.height = y - rect.y;

     

               if (rect.width <= 0 || rect.height <= 0) {  // 잘못 두번쨰 좌표 선택한 경우 취소

                   step = -1;

                   rect.x = rect.y = rect.width = rect.height = 0;

                   matMask = null;

                   return false;

               }

     

               step = 2;

               matMask = null;

               matMask = Mat.zeros(matInput.size(), matInput.type());

               matMask.submat(rect).setTo(Scalar.all(255));

           }

     

           return false;

       }

     

    @Override
    
       public boolean onTouch (View v, MotionEvent event){
    
           int width = matInput.cols();
           int height = matInput.rows();
    
           // 카메라 뷰와 이미지 좌표 맞추기
           int xOffset = (mOpenCvCameraView.getWidth() - width) / 2;
           int yOffset = (mOpenCvCameraView.getHeight() - height) / 2;
    
           int x = (int) event.getX() - xOffset;
           int y = (int) event.getY() - yOffset;
    
           if (x < 0 || y < 0 || x >= width || y >= height) {// 터치가 범위 벗어난 경우
    
               step = -1;
               rect.x = rect.y = rect.width = rect.height = 0;
               matMask = null;
               return false;
           }
    
    
           if ( step == 2) { // ROI 설정된 상태에서 또 터치하면 설정 취소
               step = -1;
               rect.x = rect.y = rect.width = rect.height = 0;
               matMask = null;
               return false;
           }
    
    
           if ((step == -1)&&((rect.x == 0 && rect.y == 0) || (rect.width != 0 && rect.height != 0))) { //첫번째 클릭
    
               step = 1;
               matMask = null;
               rect.x = x;
               rect.y = y;
               rect.width = rect.height = 0;
    
           } else if ( step == 1){  //두번째 클릭
    
               rect.width = x - rect.x;
               rect.height = y - rect.y;
    
               if (rect.width <= 0 || rect.height <= 0) {  // 잘못 두번쨰 좌표 선택한 경우 취소
                   step = -1;
                   rect.x = rect.y = rect.width = rect.height = 0;
                   matMask = null;
                   return false;
               }
    
               step = 2;
               matMask = null;
               matMask = Mat.zeros(matInput.size(), matInput.type());
               matMask.submat(rect).setTo(Scalar.all(255));
           }
    
           return false;
       }




    추가 6 : native-lib.cpp

     

       Mat &matInput = *(Mat *)matAddrInput;

       Mat &matResult = *(Mat *)matAddrResult;

     

       cvtColor(matInput, matResult, COLOR_RGBA2GRAY);

       blur( matResult, matResult, Size(5,5));

       Canny( matResult, matResult, 50, 150);

     

       blur( matResult, matResult, Size(5,5));
       Canny( matResult, matResult, 50, 150);




    참고  

     

    https://answers.opencv.org/question/55734/opencv-area-selection-on-live-camera-feed/




    포스트 작성시에는 문제 없었지만 이후 문제가 생길 수 있습니다.
    댓글로 알려주시면 빠른 시일내에 답변을 드리겠습니다.

    여러분의 응원으로 좋은 컨텐츠가 만들어집니다. 지금 본 내용이 도움이 되었다면 후원 또는 유튜브 구독 부탁드립니다. 감사합니다 : )

    유튜브 구 독 하 기
    후 원 하 기


    댓글 25

Designed by Tistory.