인터넷으로 소스를 검색하다보면 읽을 때 피로도가 증가하는 경우도 있는 것 같다.
마침 눈에 띄는 소스가 있어서 일부를 한번 수정해 보았다.
소스 출처 : https://github.com/bytefish/opencv/blob/master/eigenfaces/src/eigenfaces.cpp
Before
void Eigenfaces::compute(const vector<MAT>& src, const vector<INT>& labels) { if(src.size() == 0) { string error_message = format("Empty training data was given. You'll need more than one sample to learn a model."); CV_Error(CV_StsUnsupportedFormat, error_message); } // observations in row Mat data = asRowMatrix(src, CV_64FC1); // number of samples int n = data.rows; // dimensionality of data int d = data.cols; // assert there are as much samples as labels if(n != labels.size()) { string error_message = format("The number of samples (src) must equal the number of labels (labels). Was len(samples)=%d, len(labels)=%d.", n, labels.size()); CV_Error(CV_StsBadArg, error_message); } // clip number of components to be valid if((_num_components <= 0) || (_num_components > n)) _num_components = n; // perform the PCA PCA pca(data, Mat(), CV_PCA_DATA_AS_ROW, _num_components); // copy the PCA results _mean = pca.mean.reshape(1,1); // store the mean vector _eigenvalues = pca.eigenvalues.clone(); // eigenvalues by row _eigenvectors = transpose(pca.eigenvectors); // eigenvectors by column _labels = labels; // store labels for prediction // save projections for(int sampleIdx = 0; sampleIdx < data.rows; sampleIdx++) { Mat p = project(data.row(sampleIdx).clone()); this->_projections.push_back(p); } } void Eigenfaces::predict(const Mat& src, int &minClass, double &minDist) { if(_projections.empty()) { // throw error if no data (or simply return -1?) string error_message = "This cv::Eigenfaces model is not computed yet. Did you call cv::Eigenfaces::train?"; CV_Error(CV_StsError, error_message); } else if(_eigenvectors.rows != src.total()) { // check data alignment just for clearer exception messages string error_message = format("Wrong input image size. Reason: Training and Test images must be of equal size! Expected an image with %d elements, but got %d.", _eigenvectors.rows, src.total()); CV_Error(CV_StsError, error_message); } // project into PCA subspace Mat q = project(src.reshape(1,1)); // find 1-nearest neighbor minDist = DBL_MAX; minClass = -1; for(int sampleIdx = 0; sampleIdx < _projections.size(); sampleIdx++) { double dist = norm(_projections[sampleIdx], q, NORM_L2); if((dist < minDist) && (dist < _threshold)) { minDist = dist; minClass = _labels[sampleIdx]; } } } int Eigenfaces::predict(const Mat& src) { int label; double dummy; predict(src, label, dummy); return label; }
After
void Eigenfaces::compute(const vector<MAT> &src, const vector<INT> &labels) { string strMsgError; Mat data; int n; int d; if(src.size() == 0) { string strMsgError = format("Empty training data was given. You'll need more than one sample to learn a model."); CV_Error(CV_StsUnsupportedFormat, strMsgError); } data = asRowMatrix(src, CV_64FC1); // observations in row n = data.rows; // number of samples d = data.cols; // dimensionality of data // assert there are as much samples as labels if(n != labels.size()) { strMsgError = format("The number of samples (src) must equal the number of labels (labels). Was len(samples)=%d, len(labels)=%d.", n, labels.size()); CV_Error(CV_StsBadArg, strMsgError); } // clip number of components to be valid if((_num_components <= 0) || (_num_components > n)) _num_components = n; // perform the PCA PCA pca(data, Mat(), CV_PCA_DATA_AS_ROW, _num_components); // copy the PCA results _mean = pca.mean.reshape(1,1); // store the mean vector _eigenvalues = pca.eigenvalues.clone(); // eigenvalues by row _eigenvectors = transpose(pca.eigenvectors); // eigenvectors by column _labels = labels; // store labels for prediction // save projections for(int sampleIdx = 0; sampleIdx < data.rows; sampleIdx++) { Mat p = project( data.row(sampleIdx).clone() ); this->_projections.push_back(p); } } void Eigenfaces::predict(const Mat &src, int &minClass, double &minDist) { string strMsgError; Mat q; if(_projections.empty()) { // throw error if no data (or simply return -1?) strMsgError = "This cv::Eigenfaces model is not computed yet. Did you call cv::Eigenfaces::train?"; CV_Error(CV_StsError, strMsgError); } else if(_eigenvectors.rows != src.total()) { // check data alignment just for clearer exception messages strMsgError = format("Wrong input image size. Reason: Training and Test images must be of equal size! Expected an image with %d elements, but got %d.", _eigenvectors.rows, src.total()); CV_Error(CV_StsError, strMsgError); } // project into PCA subspace q = project(src.reshape(1,1)); // find 1-nearest neighbor minDist = DBL_MAX; minClass = -1; for(int sampleIdx = 0; sampleIdx < _projections.size(); sampleIdx++) { double dist = norm(_projections[sampleIdx], q, NORM_L2); if((dist < minDist) && (dist < _threshold)) { minDist = dist; minClass = _labels[sampleIdx]; } } } int Eigenfaces::predict(const Mat &src) { int label; double dummy; predict(src, label, dummy); return label; }
해설
큰 수정 맥락은 다음과 같다.
1. const Mat& src ==> const Mat &src
==> 좌측 코드는 변수를 여러개 선언 할 경우 마치 &가 각 변수에 적용되는 것처럼 오인될 수 있다.
==> EX) const Mat& src, dest;
==> const Mat &src, &dest; // 이것이 더 명확하다.
2. 대입문에 대한 코멘트가 상단에 위치하기도 하고 우측에 위치하기도 한다.
==> 모두 우측에 정렬되어 위치하도록 수정해 보았다.
3. 코드 중간에 변수가 선언되어 있는 부분을 될 수 있는 한 최상단에 보이도록 모아 보았다.
==> 코드 분석 시 변수 선언 파악이 더 빨라진다.
4. 함수와 함수, 메쏘드와 메쏘드 간의 간격은 2줄이다.
==> 직관적으로 함수의 끝을 더 쉽게 찾을 수 있다.
5. Allman style로 변경하였다.
==> 괄호 쌍의 짝이 안맞는 상황을 쉽게 감지 할 수 있다. 탭 역시 가장 이상적인 스타일로 생각된다.
6. 대입문이 반복될 시 이퀄은 같은 컬럼 위치에 존재하여 가독성을 높인다.
7. 로직의 흐름이 끊어지는 곳은 한 줄을 띄운다.
이처럼 수정하면 코드 가독성이 증가하여 에러를 찾거나 보수가 쉬워지지 않을까 싶다.
PS. 발행해서 보니 소스에서 코멘트의 탭이 맞지 않는데 이것은 의도된 바가 아니다.
'Tech' 카테고리의 다른 글
코드 정리 #3 (0) | 2018.07.27 |
---|---|
코드 정리 #2 (0) | 2018.07.26 |
[기초] C/C++ 에서 에러를 최소화하는 코딩 법 (0) | 2018.07.25 |
기본 Base64의 urlsafe 한 변형 버전이 있다. (0) | 2018.07.25 |
One Time Coding (0) | 2018.07.24 |