Mat BOWKMeansTrainer::cluster() const { CV_Assert( !descriptors.empty() ); int descCount = 0; for( size_t i = 0; i < descriptors.size(); i++ ) descCount += descriptors[i].rows; Mat mergedDescriptors( descCount, descriptors[0].cols, descriptors[0].type() ); for( size_t i = 0, start = 0; i < descriptors.size(); i++ ) { Mat submut = mergedDescriptors.rowRange((int)start, (int)(start + descriptors[i].rows)); descriptors[i].copyTo(submut); start += descriptors[i].rows; } return cluster( mergedDescriptors ); }
void OpponentColorDescriptorExtractor::computeImpl( InputArray _bgrImage, std::vector<KeyPoint>& keypoints, OutputArray descriptors ) const { Mat bgrImage = _bgrImage.getMat(); std::vector<Mat> opponentChannels; convertBGRImageToOpponentColorSpace( bgrImage, opponentChannels ); const int N = 3; // channels count std::vector<KeyPoint> channelKeypoints[N]; Mat channelDescriptors[N]; std::vector<int> idxs[N]; // Compute descriptors three times, once for each Opponent channel to concatenate into a single color descriptor int maxKeypointsCount = 0; for( int ci = 0; ci < N; ci++ ) { channelKeypoints[ci].insert( channelKeypoints[ci].begin(), keypoints.begin(), keypoints.end() ); // Use class_id member to get indices into initial keypoints vector for( size_t ki = 0; ki < channelKeypoints[ci].size(); ki++ ) channelKeypoints[ci][ki].class_id = (int)ki; descriptorExtractor->compute( opponentChannels[ci], channelKeypoints[ci], channelDescriptors[ci] ); idxs[ci].resize( channelKeypoints[ci].size() ); for( size_t ki = 0; ki < channelKeypoints[ci].size(); ki++ ) { idxs[ci][ki] = (int)ki; } std::sort( idxs[ci].begin(), idxs[ci].end(), KP_LessThan(channelKeypoints[ci]) ); maxKeypointsCount = std::max( maxKeypointsCount, (int)channelKeypoints[ci].size()); } std::vector<KeyPoint> outKeypoints; outKeypoints.reserve( keypoints.size() ); int dSize = descriptorExtractor->descriptorSize(); Mat mergedDescriptors( maxKeypointsCount, 3*dSize, descriptorExtractor->descriptorType() ); int mergedCount = 0; // cp - current channel position size_t cp[] = {0, 0, 0}; while( cp[0] < channelKeypoints[0].size() && cp[1] < channelKeypoints[1].size() && cp[2] < channelKeypoints[2].size() ) { const int maxInitIdx = std::max( 0, std::max( channelKeypoints[0][idxs[0][cp[0]]].class_id, std::max( channelKeypoints[1][idxs[1][cp[1]]].class_id, channelKeypoints[2][idxs[2][cp[2]]].class_id ) ) ); while( channelKeypoints[0][idxs[0][cp[0]]].class_id < maxInitIdx && cp[0] < channelKeypoints[0].size() ) { cp[0]++; } while( channelKeypoints[1][idxs[1][cp[1]]].class_id < maxInitIdx && cp[1] < channelKeypoints[1].size() ) { cp[1]++; } while( channelKeypoints[2][idxs[2][cp[2]]].class_id < maxInitIdx && cp[2] < channelKeypoints[2].size() ) { cp[2]++; } if( cp[0] >= channelKeypoints[0].size() || cp[1] >= channelKeypoints[1].size() || cp[2] >= channelKeypoints[2].size() ) break; if( channelKeypoints[0][idxs[0][cp[0]]].class_id == maxInitIdx && channelKeypoints[1][idxs[1][cp[1]]].class_id == maxInitIdx && channelKeypoints[2][idxs[2][cp[2]]].class_id == maxInitIdx ) { outKeypoints.push_back( keypoints[maxInitIdx] ); // merge descriptors for( int ci = 0; ci < N; ci++ ) { Mat dst = mergedDescriptors(Range(mergedCount, mergedCount+1), Range(ci*dSize, (ci+1)*dSize)); channelDescriptors[ci].row( idxs[ci][cp[ci]] ).copyTo( dst ); cp[ci]++; } mergedCount++; } } mergedDescriptors.rowRange(0, mergedCount).copyTo( descriptors ); std::swap( outKeypoints, keypoints ); }