2013-08-08 2 views
3

좋아, 나는 OpenCV의 초심자이며 MATLAB/lin이라는 것을 인정해야한다. 대수 지식은 편향을 도입 할 수 있습니다. 그러나 내가하고 싶은 일은 정말 간단합니다. 그래도 나는 대답을 찾을 수 없었습니다.OpenCV warpPerspective - 대상 이미지 크기를 아는 방법?

  1. 가 변형 찾기 : 투시 변환 하에서 화상 (또는 화상의 일부) 정류하려고하면

    하면 기본적 (는 왜곡 된 객체를 정의하는 4 점을 가정 함)의 두 단계를 수행 일부 완벽한 직사각형과 왜곡 된 모양 사이 (OpenCV에서 findHomography() 또는 getPerspectiveTransform()을 통해 - 왜이 두 점이 같은 점에서 다르게 작동하는지는 또 다른 이야기이며 실망 스럽습니다). 이것은 행렬 T를 제공합니다. (OpenCV에서는 warpPerspective()으로 끝납니다.) 처음 변형 된 모양에 T의 역함수를 적용하여 직사각형으로 변환합니다.

이제이 마지막 기능()은 대상 이미지의 크기를 지정하도록 사용자에게 요청합니다.

제 질문은 사용자가 미리 알고 있어야하는 크기입니다. 저레벨의 방법은 객체가있는 이미지의 모서리 점에 변형 T를 적용하는 것입니다. 따라서 새로 변형 된 모양으로 경계를 벗어나지 않도록 보장 할 수 있습니다. 그러나 매트릭스를 T에서 꺼내어 수동으로 그 점에 적용하더라도 결과가 이상하게 보입니다.

OpenCV에서이 작업을 수행 할 수있는 방법이 있습니까? 감사!

P.

float leftX, lowerY, rightX, higherY; 

float minX = std::numeric_limits<float>::max(), maxX = std::numeric_limits<float>::min(), minY = std::numeric_limits<float>::max(), maxY = std::numeric_limits<float>::min(); 

Mat value, pt; 
for(int i=0; i<4; i++) 
{ 
    switch(i) 
    { 
     case 0: 
      pt = (Mat_<float>(3, 1) << 1.00,1.00,1.00);       
      break; 
     case 1: 
      pt = (Mat_<float>(3, 1) << srcIm.cols,1.00,1.00); 
      break; 
     case 2: 
      pt = (Mat_<float>(3, 1) << 1.00,srcIm.rows,1.00); 
      break; 
     case 3: 
      pt = (Mat_<float>(3, 1) << srcIm.cols,srcIm.rows,1.00); 
      break; 
     default: 
      cerr << "Wrong switch." << endl; 
      break; 
    }    
    value = invH*pt;  
    value /= value.at<float>(2);   
    minX = min(minX,value.at<float>(0)); 
    maxX = max(maxX,value.at<float>(0)); 
    minY = min(minY,value.at<float>(1)); 
    maxY = max(maxY,value.at<float>(1)); 
} 
leftX = std::min<float>(1.00,-minX); 
lowerY = std::min<float>(1.00,-minY); 
rightX = max(srcIm.cols-minX,maxX-minX); 
higherY = max(srcIm.rows-minY,maxY-minY); 

warpPerspective(srcIm, dstIm, H, Size(rightX-leftX,higherY-lowerY), cv::INTER_CUBIC); 

UPDATE : 아래의 일부 코드이다 내가 사용 행렬이 잘못 때문에 아마도 내 결과가 좋아 보이지 않습니다. getPerspectiveTransform() 내부에서 일어나는 일을 관찰 할 수 없기 때문에이 행렬이 어떻게 계산되는지는 알 수 없지만 매우 작고 매우 큰 값을 가지기 때문에 쓰레기라고 생각합니다. 이 I는 T에서 데이터를 획득하는 방법이다

for(int row=0;row<3;row++) 
    for(int col=0;col<3;col++) 
     T.at<float>(row,col) = ((float*)(H.data + (size_t)H.step*row))[col]; 

이인가 (getPerspectiveTransform()의 출력 행렬은 3 × 3은 분할 폴트 T.at<float>(row,col) 리드를 통해 직접 값을 액세스하려고하지만). 그것을 할 올바른 방법? 아마도 올바른 행렬을 얻지 못했기 때문에 원래의 문제가 발생했을 것입니다 ...

+0

저수준 방식이 나에게 맞는 것 같습니다. "결과가 이상하게 보인다"는 것은 무엇을 의미합니까? 문제를 보여주기 위해 최소한의 예제 코드를 만들 수 있습니까? –

+0

나는 내가 얻은 좌표가 원본 이미지의 내부에 있다는 것을 의미한다. (이미지를 표시하기 때문에 그 결과가 이상하게 보일 뿐이고, 그 부분 일 뿐이다.) 이는 아마도 행렬 T가 내가 기대 한 것과 다르다는 것을 의미한다. 정상화되었거나 그와 비슷한 것이지, 포인트를 직접 조작하지 않아도 되는가? ...? – bloodymir

+0

@Dobi 먼저 행렬 값을 얻는 방법에 대한 코드를 추가했습니다. 아마도 이것은 오류가 발생하는 곳입니다 ... – bloodymir

답변

0

결과가 wierd로 보일 경우 아마도 포인트가 getPerspectiveTransform에 올바르게 설정되지 않았기 때문일 수 있습니다. 포인트 벡터는 올바른 순서 (왼쪽 위, 오른쪽 위, 오른쪽 아래, 왼쪽 아래)에 있어야합니다.

하지만 초기 질문에 답하기 위해 "최적 출력 크기"와 같은 것은 없습니다. 당신이하고 싶은 일에 따라 결정해야합니다. 시도해보고 맞는 크기를 찾으십시오.

편집 : 문제가 변환 행렬에서 오는

, 어떻게 당신이 그것을 만들 수 있습니까?openCV에서 좋은 방법은 다음과 같습니다.

vector<Point2f> corners; 
corners.push_back(topleft); 
corners.push_back(topright); 
corners.push_back(bottomright); 
corners.push_back(bottomleft); 


// Corners of the destination image 
// output is the output image, should be defined before this operation 
vector<cv::Point2f> output_corner; 
output_corner.push_back(cv::Point2f(0, 0)); 
output_corner.push_back(cv::Point2f(output.cols, 0)); 
output_corner.push_back(cv::Point2f(output.cols, output.rows)); 
output_corner.push_back(cv::Point2f(0, output.rows)); 

// Get transformation matrix 
Mat H = getPerspectiveTransform(corners, output_corner); 
+0

이미지의 일부 (또는 일부)가 올바르게 수정되었으므로 올바른 순서로 표시됩니다. 출력에 대해 충분히 큰 크기를 수동으로 지정하지 않으면 포인트가 잘립니다. Btw, 포인트의 순서가 항상 동일하다면, 당신이 제안하는 순서가 고정되어야한다는 것은 사실이 아닐 것입니다. 시행 착오만으로 출력 이미지를 적절한 크기로 맞출 수있는 유일한 방법이라면 나는 그것이 매우 우스꽝 스럽다. – bloodymir

+0

자른 이미지로 무엇을하고 싶습니까? 이미지에서 자르는 세부 사항의 크기는 무엇입니까? 자동으로 감지 할 수없는 것들입니다. –

+0

정확하게 이해한다면 규모의 문제가 아니라 자르기 문제입니다. 내가 원하는 것은 정사각형 사각형의 크기에 이미지 크기를 맞추는 것입니다. 이 작업을 수행하는 저수준 방법이 있습니다 (Dobi와의 교환 참조).하지만 작동하지 않는 것 같습니다 (수학적으로 말하면, 뒤틀림은 모든 점에 변형 행렬 T를 곱하는 것입니다). 그렇다면이 직사각형의 범위가 무엇인지 어떻게 알 수 있습니까? – bloodymir

관련 문제