복붙노트

[PYTHON] 파이썬에서 opencv를 사용하여 이미지의 회전 사각형 영역을 교정하는 방법은 무엇입니까?

PYTHON

파이썬에서 opencv를 사용하여 이미지의 회전 사각형 영역을 교정하는 방법은 무엇입니까?

다음 사진은 내가 원하는 것을 알려줍니다.

이미지, 폭, 높이, 중심점 및 회전 각도에서 직사각형의 정보를가집니다. 자, 그들을 잘라내어 이미지로 저장하는 스크립트를 작성하고 싶습니다. 마찬가지로 내가 이미지 내부에 표시된 사각형에서 외부에 표시된 사각형으로 가고 싶습니다.

OpenCV Python을 사용하고 있습니다.이 방법을 알려주십시오.

오픈 코드 (OpenCV)의 예로서 어떤 코드를 보여 주면 파이썬을 찾기가 어렵습니다.

해결법

  1. ==============================

    1.warpAffine 함수를 사용하여 정의 된 중심점 주위로 이미지를 회전 할 수 있습니다. 적절한 회전 행렬은 getRotationMatrix2D (여기서 theta는도 단위)를 사용하여 생성 할 수 있습니다.

    warpAffine 함수를 사용하여 정의 된 중심점 주위로 이미지를 회전 할 수 있습니다. 적절한 회전 행렬은 getRotationMatrix2D (여기서 theta는도 단위)를 사용하여 생성 할 수 있습니다.

    그런 다음 Numpy 슬라이싱을 사용하여 이미지를자를 수 있습니다.

    import cv2
    import numpy as np
    
    def subimage(image, center, theta, width, height):
    
       ''' 
       Rotates OpenCV image around center with angle theta (in deg)
       then crops the image according to width and height.
       '''
    
       # Uncomment for theta in radians
       #theta *= 180/np.pi
    
       shape = image.shape[:2]
    
       matrix = cv2.getRotationMatrix2D( center=center, angle=theta, scale=1 )
       image = cv2.warpAffine( src=image, M=matrix, dsize=shape )
    
       x = int( center[0] - width/2  )
       y = int( center[1] - height/2 )
    
       image = image[ y:y+height, x:x+width ]
    
       return image
    

    dsize는 출력 이미지의 모양입니다. 패치 / 각도가 충분히 큰 경우, 위의 단순화를 위해 원래 모양을 사용하는 경우 가장자리가 잘립니다 (위 이미지 비교 참조). 이 경우, 출력 이미지를 확대하기 위해 모양을 지정하는 배율 요소와 슬라이스를위한 참조 점 (여기서는 가운데)을 도입 할 수 있습니다.

    위의 함수는 다음과 같이 사용할 수 있습니다.

    image = cv2.imread('owl.jpg')
    image = subimage(image, center=(110, 125), theta=30, width=100, height=200)
    cv2.imwrite('patch.jpg', image)
    
  2. ==============================

    2.여기와 비슷한 질문에 대한 잘못된 오프셋 문제가있었습니다. 그래서 저는 수학을하고 다음과 같은 해답을 제시했습니다 :

    여기와 비슷한 질문에 대한 잘못된 오프셋 문제가있었습니다. 그래서 저는 수학을하고 다음과 같은 해답을 제시했습니다 :

    def subimage(self,image, center, theta, width, height):
        theta *= 3.14159 / 180 # convert to rad
    
        v_x = (cos(theta), sin(theta))
        v_y = (-sin(theta), cos(theta))
        s_x = center[0] - v_x[0] * ((width-1) / 2) - v_y[0] * ((height-1) / 2)
        s_y = center[1] - v_x[1] * ((width-1) / 2) - v_y[1] * ((height-1) / 2)
    
        mapping = np.array([[v_x[0],v_y[0], s_x],
                            [v_x[1],v_y[1], s_y]])
    
        return cv2.warpAffine(image,mapping,(width, height),flags=cv2.WARP_INVERSE_MAP,borderMode=cv2.BORDER_REPLICATE)
    

    참고 자료는 그 뒤에있는 수학을 설명하는 이미지입니다.

    유의 사항

    w_dst = width-1
    h_dst = height-1
    

    이는 마지막 좌표가 너비가 아닌 width-1 값을 가지기 때문입니다. 또는 높이.

    수학에 대해 질문이 있으면 의견을 물어보고 대답을 시도합니다.

  3. ==============================

    3.이것은 동일한 작업을 수행하는 C ++ 버전입니다. 나는 그것이 약간 느리다 것을 알아 챘다. 누군가이 기능의 성능을 향상시킬만한 것을 발견하면 알려주십시오. :)

    이것은 동일한 작업을 수행하는 C ++ 버전입니다. 나는 그것이 약간 느리다 것을 알아 챘다. 누군가이 기능의 성능을 향상시킬만한 것을 발견하면 알려주십시오. :)

    bool extractPatchFromOpenCVImage( cv::Mat& src, cv::Mat& dest, int x, int y, double angle, int width, int height) {
    
      // obtain the bounding box of the desired patch
      cv::RotatedRect patchROI(cv::Point2f(x,y), cv::Size2i(width,height), angle);
      cv::Rect boundingRect = patchROI.boundingRect();
    
      // check if the bounding box fits inside the image
      if ( boundingRect.x >= 0 && boundingRect.y >= 0 &&
           (boundingRect.x+boundingRect.width) < src.cols &&  
           (boundingRect.y+boundingRect.height) < src.rows ) { 
    
        // crop out the bounding rectangle from the source image
        cv::Mat preCropImg = src(boundingRect);
    
        // the rotational center relative tot he pre-cropped image
        int cropMidX, cropMidY;
        cropMidX = boundingRect.width/2;
        cropMidY = boundingRect.height/2;
    
        // obtain the affine transform that maps the patch ROI in the image to the
        // dest patch image. The dest image will be an upright version.
        cv::Mat map_mat = cv::getRotationMatrix2D(cv::Point2f(cropMidX, cropMidY), angle, 1.0f);
        map_mat.at<double>(0,2) += static_cast<double>(width/2 - cropMidX);
        map_mat.at<double>(1,2) += static_cast<double>(height/2 - cropMidY);
    
        // rotate the pre-cropped image. The destination image will be
        // allocated by warpAffine()
        cv::warpAffine(preCropImg, dest, map_mat, cv::Size2i(width,height)); 
    
        return true;
      } // if
      else {
        return false;
      } // else
    } // extractPatch
    
  4. ==============================

    4.openCV 버전 3.4.0과 비슷한 제조법.

    openCV 버전 3.4.0과 비슷한 제조법.

    from cv2 import cv
    import numpy as np
    
    def getSubImage(rect, src):
        # Get center, size, and angle from rect
        center, size, theta = rect
        # Convert to int 
        center, size = tuple(map(int, center)), tuple(map(int, size))
        # Get rotation matrix for rectangle
        M = cv2.getRotationMatrix2D( center, theta, 1)
        # Perform rotation on src image
        dst = cv2.warpAffine(src, M, src.shape[:2])
        out = cv2.getRectSubPix(dst, size, center)
        return out
    
    img = cv2.imread('img.jpg')
    # Find some contours
    thresh2, contours, hierarchy = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    # Get rotated bounding box
    rect = cv2.minAreaRect(contours[0])
    # Extract subregion
    out = getSubImage(rect, img)
    # Save image
    cv2.imwrite('out.jpg', out)
    
  5. from https://stackoverflow.com/questions/11627362/how-to-straighten-a-rotated-rectangle-area-of-an-image-using-opencv-in-python by cc-by-sa and MIT license