OpenCV 와 C++기반 그림 회전

그림 이 회전 하 는 것 은 본질 적 으로 회전 한 그림 의 모든 픽 셀 점 을 원 그림 의 위치 에 계산 하 는 것 이다.그냥 옮 겨 오 면 돼.
(한 마디 더 하 자 면 원 그림 에서 의 위 치 를 정수 가 아니 라 소수 로 계산 하면 픽 셀 점 의 개수 가 모두 정수 이기 때문에 소수 에서 정수 로 전환 해 야 한다.이 전환 과정 은 중요 한 것 이 므 로 삽입 값 을 사용 해 야 한다.최근 에 인접 한 삽입 값,이중 선형 삽입 값 등 이다.여기 서 제 가 사용 하 는 것 은 가장 간단 한 최근 인접 플러그 인 입 니 다.즉,소수 반올림 을 정수 로 하고 C/C++반올림 을 실현 합 니 다.
도형 이미지 수업 에서 회전 변환 행렬 을 소개 하 는데 그 중에서 t 는 회전 이 필요 한 각도 이다.[x';y']는 변 경 된 좌표(그 중에서 분 호 는 상하 관 계 를 나타 낸다)입 니 다.

즉,[x'이다.y'] = [cos(t) sin(t); -sin(t) cos(t)][x; y]
제 개인 적 인 취미 때문에...OpenCV 로 봉 인 된 회전 함 수 를 사용 할 수 없습니다.스스로 실현 할 수 밖 에 없다.내 가 시작 한 생각 은 먼저 행렬 의 역 행렬 을 바 꾼 다음 에 전체 검 은 그림 의 모든 점 을 원 그림 에 일일이 대응 하 는 것 이다.
바 뀌 어서 사진 이 다 까 매 졌 더 라 고요.................................................
원점 설정 이 잘못 되 었 다 는 것 을 알 게 되 었 다.OpenCV 의 Mat 형식 으로(또는 2 차원 배열)그림 을 저장 하고 원점 은 왼쪽 상단 에 있 습 니 다.하지만 실현 하고 자 하 는 회전 원점 은 그림 중심 에 있다.
동시에 Mat 형식 저장(또는 2 차원 배열)의 좌표계 에서 y 축 은 방향 을 아래로 향 합 니 다.이렇게 하면 인류 시각 에서 시계 방향 으로 회전 하고 2 차원 배열 의 좌표계 에서 시계 반대 방향 으로 회전한다.
가장 중요 한 것 은 2 차원 배열 작업 에서 무시 하기 쉬 운 점 입 니 다.배열 작업 은 배열 아래 표 시 를 하 는 것 입 니 다.좌표계(배열 의 줄 수 rows 는 사각형 의 너비 width 이 고 열 수 cols 는 사각형 의 긴 length)가 아 닙 니 다.예 를 들 어 좌표계(이때 배열 의 구조 에 더욱 가 까 워 지기 위해 우 리 는 y 축 좌표계 가 아래 라 고 가정 합 니 다)에서 사각형 의 정점 은:

그러나 배열 에 서 는 줄 이 우선 이기 때문에 네 개의 점 아래 표 시 된 값 은:

두 좌표 가 반대 라 는 것 을 발 견 했 습 니까?
요약 하면 우리 의 그림 회전 은 다음 과 같은 몇 가 지 를 주의해 야 한다.
  • 변 경 된 그림 의 모든 픽 셀 점(i;j)상대 적 으로 회전 하 는 중심 으로 이동 하 는 새로운 좌표,즉(i-Mat.rows/2;j - Mat.cols/2)。계산 이 끝 난 후에 상대 적 으로 왼쪽 상단 원점 의 낡은 좌표 로 다시 복원 해 야 합 니 다
  • 4.567917.원래 변환 한 후에 그림 에 원 도 를 곱 하여 행렬 을 바 꾸 는 역 행렬 은 원 그림 의 좌표 에 대응 해 야 한다.그러나 Y 축 방향 이 아래로 향 하기 때문에 변환 후 그림 에 원 도 를 곱 하여 행렬 을 바 꾸 면 원 그림 의 좌표(시계 방향 으로 50 도 회전 하고 복원 작업 은 시계 반대 방향 으로 50 도 회전)에 대응 할 수 있다4.567917.행렬 아래 표 와 원 도 를 행렬 로 바 꾸 기 전에 행렬 아래 표 시 된 두 값 을 교환 해 야 한다.곱 한 후에 다음 표 시 를 다시 바 꾸 어 행렬 아래 표 시 를 복원 해 야 합 니 다따라서 회전 t 도 를 거 친 후에 배열 아래 에[m',n']로 표 시 된 픽 셀 값 을 원 그림 의 배열 아래 표 시 된[m 로 복원 합 니 다.n]계산:
    [cos(t) -sin(t); sin(t) cos(t)] ([m'; n'] - [Mat.rows/2; Mat.cols/2]) = [m; n] -  [Mat.rows/2; Mat.cols/2]
    원본 코드 첨부:
    
    Mat nearestNeighRotate(cv::Mat img, float angle)
    {
    	int len = (int)(sqrtf(pow(img.rows, 2) + pow(img.cols, 2)) + 0.5);
    
    	Mat retMat = Mat::zeros(len, len, CV_8UC3);
    	float anglePI = angle * CV_PI / 180;
    	int xSm, ySm;
    
    	for(int i = 0; i < retMat.rows; i++)
    		for(int j = 0; j < retMat.cols; j++)
    		{
    			xSm = (int)((i-retMat.rows/2)*cos(anglePI) - (j-retMat.cols/2)*sin(anglePI) + 0.5);
    			ySm = (int)((i-retMat.rows/2)*sin(anglePI) + (j-retMat.cols/2)*cos(anglePI) + 0.5);
    			xSm += img.rows / 2;
    			ySm += img.cols / 2;
    
    			if(xSm >= img.rows || ySm >= img.cols || xSm <= 0 || ySm <= 0){
    				retMat.at<Vec3b>(i, j) = Vec3b(0, 0);
    			}
    			else{
    				retMat.at<Vec3b>(i, j) = img.at<Vec3b>(xSm, ySm);
    			}
    		}
    
    	return retMat;
    }
    자,테스트 해 봅 시다.
    
    int main() 
    { 
    	Mat img = imread("../HelloWorld.png");
    	retImg = nearestNeighRotate(img, -20.f);
    	namedWindow("nearNeigh", CV_WINDOW_AUTOSIZE);
    	imshow("nearNeigh", retImg);
    
    	waitKey(); 
    	cvDestroyAllWindows();
    	return 0; 
    }
    결과

    이상 은 OpenCV 와 C++를 바탕 으로 이미지 회전 을 실현 하 는 상세 한 내용 입 니 다.c+이미지 회전 에 관 한 자 료 는 저희 의 다른 관련 글 을 주목 하 세 요!

    좋은 웹페이지 즐겨찾기