저수준 포인터 산술 연산 low level pointer calculation operation
if (image.isContinuous ()){|| 채운 화소가 없을 경우image.reshape (1,// 채널의 새로운 값image.cols image.rows); // 행의 새로운 값1int nl= image.rows; // 행 개수int nc= image.cols image.channels ();
reshape 메소드는 임의의 메모리 복사나 재할당 없이 행렬의 차원 수를 변경한다. 첫 번째 파라미터는 새로운 채널 개수이고, 두 번째 파라미터는 새로운행 개수다. 이에 맞춰 열 개수가 조절된다.
이번 구현에서 내부 반복문은 모든 영상 화소를 순차적으로 처리한다. 여러개의 작은 영상을 같은 반복문에서 동시에 조회할 때 주로 유리하다.
cv:Mat 클래스에서 영상 데이터는 unsigned char로 구성된 메모리 블록에 들어가 있다. unsigned char 포인터를 반환하는 데이터 속성에는 메모리 블록의첫 번째 요소인 주소를 갖는다. 따라서 영상을 갖고 반복문을 시작할 때 다음과같이 쓸 수 있다.
uchar *data= image.data;
유효 너비를 사용해 행 포인터를 이동하면 하나씩 다음 행으로 이동할 수있다.
data+= image.step; // 다음 줄
step 메소드는 해당 행의 바이트 총 개수 채운 화소를 포함)를 제공한다. 일반적으로 다음과 같이 행 j와 열 i에 놓인 화소의 주소를 얻을 수 있다.
pixel operation calculation 화소 연산하는 방법
Extracted Frame
예제 분석
비디오를 열려면 비디오 파일명을 간단히 지정해야 하는데, CV:: VideoCapture객체의 생성자에 파일명을 제공해 수행할 수 있다. 또한 이미 생성했던CV:: VideoCapture의 open 메소드를 이용할 수도 있다. 비디오를 성공적으로열었다면(isopened 메소드를 통해 검증할 수 있다) 프레임 추출을 시작할 수 있다. 또한 cv:: VideoCapture 객체에서 적절한 플래그와 함께 get 메소드를 사용해비디오 파일과 연계된 정보를 조회할 수 있다. 앞의 예제에서 CV CAPPROP FPS 플래그를 사용해 프레임 속도를 얻었다. 일반적인 함수이기 때문에어떤 경우에는 다른 타입이 예상될 경우 항상 이중으로 반환한다. 예제에서 비디오 파일의 프레임 총 개수를 다음과 같이 얻는다(정수로),
long t= static_castclong> ( capture.get (CV_CAP_PROP_FRAME_COUNT));
비디오에서 얻을 수 있는 정보를 확인하려면 OpenCV 문서에서 사용할 수있는 다른 플래그를 살펴보라.
또한 cv:: VideoCapture 인스턴스에 여러 가지 파라미터를 입력할 수 있는set 메소드가 있다. 예를 들어 CV CAP PROP POS FRAME을 사용해 특정 프레임을 이동하게 요청할 수 있다.
// 100번째 프레임으로 가기
double position= 100.0;
sobel operation 소벨 연산과 캐니연산자의 계산 방법
캐니 연산자는 일반적으로 소벨 연산자에 기반을 두지만, 다른 기울기 연산자를사용할 수 있다. 여기서 핵심 아이디어는 점이 외곽선에 속하는지 조사하기 위한 낮고 높은 경계값인 다른 두 경계값을 사용하는 데 있다.
낮은 경계값은 중요한 영상 외곽선에 속하는 것으로 간주하는 모든 에지 화소를 포함하는 방법으로 선택해야 한다. 예를 들어 이전 절의 예제에서 지정한낮은 경계값을 사용하고, 소벨 연산자 결과에 적용하면 다음과 같은 이진 맵을얻는다.
Sobel (low threshold)
그림에서 보듯 도로를 기술한 에지를 매우 잘 정의한다. 그러나 허용 경계값을 사용했기 때문에 이상적으로 필요한 것보다 더 많은 에지를 감지했다. 두번째 경계값의 역할은 모든 중요한 외곽선에 속하는 에지를 정의한다. 영외Outlier로 간주되는 모든 에지를 제외한다. 예를 들어 소벨 에지맵은 다음 예제에서 사용한 높은 경계값에 해당한다.
image.copyTo (foreground, result); // 배경 화소는 복사되지 않음
결과 영상은 다음과 같다.
Foreground objects
예제 분석
이전 예제에서 그랩컷 알고리즘은 간단히 객체(네 개 동물)가 포함된 직사각형 내부를 지정해 전경 객체를 추출할 수 있었다. 또한 cv::grabCut 함수의 두 번째인자로 분할 영상의 특정 일부 화소인 cv:: GC_BGD와 cv:: FGD 값을 할당할 수있다. 그런 후에 입력 모드 플래그인 GC_INIT WITH_MASK를 지정한다. 입력레이블을 얻을 수 있는데, 예를 들어 사용자가 대화식으로 입력 영상의 몇 가지요소를 마크한다. 또한 두 가지 입력 모드를 조합하는 것도 가능하다.
입력 정보를 사용하면 그랩컷은 다음과 같이 배경/전경 분할을 생성한다. 처음에 전경 레이블(cv:: GC_PR_FGD)에 잠정적으로 마크하지 않은 모든 화소를 할당한다. 현재 분류에 기반을 두고, 이 알고리즘은 화소를 유사 컬러의 클러스터(즉,배경 K 클러스터와 전경 K 클러스터)로 묶는다. 다음 단계는 전경과 배경 화소 간의경계를 이용해 배경/전경 분할을 결정한다. 유사한 레이블을 갖는 화소의 연결은 최적화 과정을 통해 수행하고, 상대적으로 균등한 명암도를 갖는 영역 내의경계 위치에 대해서는 패널티로 봉쇄한다. 최적화 문제는 그랩컷 알고리즘을사용해 효율적으로 해결할 수 있고, 이 방법은 최적 구성을 조합하기 위해 컷이적용된 연결 그래프를 대표해 문제에 대한 최적 해결책을 찾을 수 있다. 취득한
-1인 화소를 0(-1*255+255=0인 이후)으로 변환하게 미리 바꾼 후 선형 변환을적용한다.
255보다 큰 값을 갖는 화소값에 255를 할당한다. 이것은 부호 있는 정수를부호 없는 정수로 변환할 때 적용하는 새터레이션 연산에 따른다.
참고 사항
The viscous watershed transform by C. Vachier, F. Meyer, Journal of Mathematical Imaging and Vision, volume 22, issue 2-3, May 2005의 논문에 는 워터쉐드 알고리즘에 대해 더 많은 정보를 제공한다.
다음 예제는 영상 내의 배경과 전경 객체를 분할할 수 있는 다른 영상 분할알고리즘을 다룬다.
그랩컷 알고리즘으로 전경 객체 object extraction operation
OpenCV는 영상 분할에 대한 인기 있는 다른 알고리즘인 그랩컷GrahCuu 알고리즘을 제안한다. 이 알고리즘은 수학적 형태학에 기반을 두지 않지만, 이전 예제에서 다뤘던 워터쉐드 분할 알고리즘 사용과 몇 가지 유사한 점을 제시한다. 그랩컷은 워터쉐드보다 계산하는 데 더 많은 비용이 들지만, 일반적으로 좀 더 정확한결과를 만든다. 정지 영상에서 전경 객체를 추출하기 원할 때(예를 들어 한 장의 사진에서 객체를 잘라내고 다른 데에 붙여 넣기) 사용하는 가장 좋은 알고리즘이다.
예제 구현
cv::grabCut 함수의 사용법은 쉽다. 단지 영상과 배경 또는 전경에 속하는화소의 일부인 레이블이 필요할 뿐이다. 부분 레이블링에 기반을 두며, 이 알고리즘은 영상 전체에 걸쳐 전경/배경 분할을 결정한다.
형태학 operation을 이용한 영상 transformation
앞의 결과에 실망했을 수 있는데, 잘못 감지된 영역을 구름에 추가했기 때문이다. 간단한 그레이레벨 히스토그램에서 추출한 확률 함수를 이해함이 중요하다. 영상 내 다른 많은 화소가 구름 화소와 같은 명암도를 공유하고 있고, 히스토그램을 역투영할 때 같은 확률 값을 동일한 명암도의 화소로 바꿨기 때문이다. 한 가지 해결책은 컬러 정보를 사용해 결과를 감지해 개선하는 것이다. 그러나 이 작업을 하려면 cv:: calcBackProject를 호출하는 부분을 수정할 필요가 있다.
cv:: calcBackProject 함수는 cv::calcHist 함수와 유사하다. 첫 번째 파라미터는 입력 영상을 지정한다. 그 후 사용하길 원하는 채널 번호를 나열해야 한다. 히스토그램을 입력 파라미터로 함수에게 넘긴다. 그 히스토그램은 정규화를 거쳐야 하고, 차원은 채널 목록 배열 중 하나여야 하고, 마찬가지로 ranges 파라미터 중 하나여야 한다. 그 다음은 cv:: calcHist와 마찬가지로 부동소수점 배열의 배열이되 채널별로 지정한 각 범위(최소와 최댓값)다. 출력 결과는 계산된 확률 맵인 영상이다. 각 화소는 히스토그램에서 대응하는 빈도 위치에 있는 값으로 대치한 이후로, 결과 영상은 0.0과 1.0(정규화된 히스토그램으로서 입력으로 제공했다고 가정) 사이의 값을 갖는다. 마지막 파라미터는 선택적으로 지정한 인자와 그 값을 곱해 다시 스케일링한다.
Detection Result 탐지 연산 결과 분석
앞의 결과에 실망했을 수 있는데, 잘못 감지된 영역을 구름에 추가했기 때문이다. 간단한 그레이레벨 히스토그램에서 추출한 확률 함수를 이해함이 중요하다. 영상 내 다른 많은 화소가 구름 화소와 같은 명암도를 공유하고 있고, 히스토그램을 역투영할 때 같은 확률 값을 동일한 명암도의 화소로 바꿨기 때문이다. 한 가지 해결책은 컬러 정보를 사용해 결과를 감지해 개선하는 것이다. 그러나 이 작업을 하려면 cv::calcBackProject를 호출하는 부분을 수정할 필요가 있다.
cv:: calcBackProject 함수는 cv:: calcHist 함수와 유사하다. 첫 번째 파라미터는 입력 영상을 지정한다. 그 후 사용하길 원하는 채널 번호를 나열해야 한다. 히스토그램을 입력 파라미터로 함수에게 넘긴다. 그 히스토그램은 정규화를 거쳐야 하고, 차원은 채널 목록 배열 중 하나여야 하고, 마찬가지로 ranges 파라미터 중 하나여야 한다. 그 다음은 cv:: calcHist와 마찬가지로 부동소수점 배열의 배열이되 채널별로 지정한 각 범위(최소와 최댓값)다. 출력 결과는 계산된 확률 맵인 영상이다. 각 화소는 히스토그램에서 대응하는 빈도 위치에 있는 값으로 대치한 이후로, 결과 영상은 0.0과 1.0(정규화된 히스토그램으로서 입력으로 제공했다고 가정) 사이의 값을 갖는다. 마지막 파라미터는 선택적으로 지정한 인자와 그 값을 곱해 다시 스케일링한다.
148
댓글