OpenCV의 (OSX) 파이썬 2.7.5를 사용하는 경우, 나는 일련의 이미지에 PCA를 실행 (COLS 픽셀은 행은 프레임 this answer에 따라 있습니다.파이썬 OpenCV의 PCACompute 고유치
나는 고유은 해당 얻는 방법 그것은 C++에서 PCA 개체의 속성은, 그러나 동등한 파이썬 PCACompute()
간단한 기능처럼 고유 벡터에? 같습니다.
OpenCV의 (OSX) 파이썬 2.7.5를 사용하는 경우, 나는 일련의 이미지에 PCA를 실행 (COLS 픽셀은 행은 프레임 this answer에 따라 있습니다.파이썬 OpenCV의 PCACompute 고유치
나는 고유은 해당 얻는 방법 그것은 C++에서 PCA 개체의 속성은, 그러나 동등한 파이썬 PCACompute()
간단한 기능처럼 고유 벡터에? 같습니다.
matmul.cpp이 PCA::Operator()
가되고있는 확인 PCACompute()
에 의해 사용되었지만, eigenv 경고는 무시됩니다.
이 거의 작품;
# The following mimics PCA::operator() implementation from OpenCV's
# matmul.cpp() which is wrapped by Python cv2.PCACompute(). We can't
# use PCACompute() though as it discards the eigenvalues.
# Scrambled is faster for nVariables >> nObservations. Bitmask is 0 and
# therefore default/redundant, but included to abide by online docs.
covar, mean = cv2.calcCovarMatrix(PCAInput, cv2.cv.CV_COVAR_SCALE |
cv2.cv.CV_COVAR_ROWS |
cv2.cv.CV_COVAR_SCRAMBLED)
eVal, eVec = cv2.eigen(covar, computeEigenvectors=True)[1:]
# Conversion + normalisation required due to 'scrambled' mode
eVec = cv2.gemm(eVec, PCAInput - mean, 1, None, 0)
# apply_along_axis() slices 1D rows, but normalize() returns 4x1 vectors
eVec = numpy.apply_along_axis(lambda n: cv2.normalize(n).flat, 1, eVec)
(.. 그리고 더 많은 변수가 관측보다 거기 모두 내 경우에는 해당 행 = 관찰, COLS = 변수 가정을 단순화 :) 그래서 이런 짓을 . 출력의 단부를 향해 표시 정밀도의 손실의 일종이있다
In [101]: eVec
Out[101]:
array([[ 3.69396088e-05, 1.66745325e-05, 4.97117583e-05, ...,
0.00000000e+00, 0.00000000e+00, 0.00000000e+00],
[ -7.23531536e-06, -3.07411122e-06, -9.58259793e-06, ...,
0.00000000e+00, 0.00000000e+00, 0.00000000e+00],
[ 1.01496237e-05, 4.60048715e-06, 1.33919606e-05, ...,
0.00000000e+00, 0.00000000e+00, 0.00000000e+00],
...,
[ -1.42024751e-04, 5.21386198e-05, 3.59923394e-04, ...,
0.00000000e+00, 0.00000000e+00, 0.00000000e+00],
[ -5.28685812e-05, 8.50139472e-05, -3.13278542e-04, ...,
0.00000000e+00, 0.00000000e+00, 0.00000000e+00],
[ 2.96546917e-04, 1.23437674e-04, 4.98598461e-04, ...,
0.00000000e+00, 0.00000000e+00, 0.00000000e+00]])
In [102]: old_eVec
Out[102]:
array([[ 3.69395821e-05, 1.66745194e-05, 4.97117981e-05, ...,
0.00000000e+00, 0.00000000e+00, 0.00000000e+00],
[ -7.23533140e-06, -3.07411415e-06, -9.58260534e-06, ...,
0.00000000e+00, 0.00000000e+00, 0.00000000e+00],
[ 1.01496662e-05, 4.60050160e-06, 1.33920075e-05, ...,
0.00000000e+00, 0.00000000e+00, 0.00000000e+00],
...,
[ -1.42029530e-04, 5.21366564e-05, 3.60067672e-04, ...,
0.00000000e+00, 0.00000000e+00, 0.00000000e+00],
[ -5.29163444e-05, 8.50261567e-05, -3.13150231e-04, ...,
0.00000000e+00, 0.00000000e+00, 0.00000000e+00],
[ -7.13724992e-04, -8.52700090e-04, 1.57953508e-03, ...,
0.00000000e+00, 0.00000000e+00, 0.00000000e+00]], dtype=float32)
(비록 절대 차의 사실 빠른 묘화가 부정확에 어떤 패턴을 보여준다 없음) : 이하, old_eVec
는 cv2.PCACompute()
의 결과이다.
요소의 57 %가 0이 아닌 절대 차를 갖습니다.
이들 중 95 %는 2e-16 미만이고 평균 AD는 5.3e-4입니다. 그러나 AD는 0.059로 높을 수 있습니다. 모든 고유 벡터 값이 -0.048 ~ 0.045.
PCA::Operator()
에는 가장 큰 ctype로 변환되는 코드가 있습니다. 반면에 old_eVec
은 float32를 생성하는 내 코드와 비교하여 float32였습니다. numpy를 컴파일 할 때 몇 가지 정밀도 관련 오류가 있다는 것을 언급 할 가치가 있습니다.
전반적으로 정밀도의 손실은 반올림 오류 등을 다시 지적하는 고유치가 낮은 고유 벡터와 관련이있는 것으로 보입니다. 위의 구현은 PCACompute()와 유사한 결과를 생성하여 동작을 복제했습니다.
Great Answer :) 그러나 코드에 필요한 몇 가지 관련 업데이트를 발견했습니다. 'calcCovarMatrix()'에 전달 된 플래그는 이제'cv2.COVAR_NORMAL'의 형태 여야합니다 (예 : cv와 CV_를 버림). 또한,'eigen()'메소드는 더 이상'computeEigenvectors' 매개 변수를 수신하지 않습니다; 실제로 매개 변수를 추가하지 않고도 covar 행렬을 사용하면 저에게 효과적이었습니다. 그 업데이트로 나는 이것을 성취 할 수있었습니다. 고마워요. – DarkCygnus
나는 당신의 코드를 시도해 보았고 어떤 이미지 데이터에서 비슷한 결과를 얻었지만, 두 방법 모두에 대한 고유 벡터 간의 차이는 꽤 낮은 고유 값을 얻은 마지막 것들 외에 1e-9의 순서이다. 수치 정밀도 일 수 있습니다 ... –
나는 동의하고 싶습니다.이 질문은 수치 계산과 행렬 분해에 익숙하지 않은 채 게시되었습니다. – benxyzzy