void OpticalMusic::rotate(Angle amount) { int width = image.cols; int height = image.rows; // compute rotation matrix (homogenous coordinates) Point center(width / 2.f, height / 2.f); Mat rotMat = getRotationMatrix2D(center, amount.degree(), 1.0); // calculate size of the new image Mat topLeft = (Mat_<double>(3, 1) << 0, 0, 1); // homogenous coordinates topLeft = rotMat * topLeft; int dx = abs(round(topLeft.at<double>(Point(0, 0)))); int dy = abs(round(topLeft.at<double>(Point(0, 1)))); Size newSize(width + 2 * dx, height + 2 * dy); // pad old image Mat padded = Mat::zeros(newSize, CV_8U); Mat targetRegion = padded(Range(dy, dy + height), Range(dx, dx + width)); image.copyTo(targetRegion); // rotate padded Mat* rotated = new Mat(newSize, CV_8UC1); warpAffine(padded, *rotated, rotMat, newSize); image = *rotated; }
/** * Performs a range query in the R-Tree, where the range is defined by the center +- the tolerances given. * @param center The center of the query volume. * @param xTolerance The absolute values to add and subtract to obtain the range in x dimension. * @param yTolerance * @param angleTolerance * @return All points within the specified interval. */ vector<ContourIndex::ContourPointIdx> ContourIndex::symmetricRange(Contour::ContourPart center, float xTolerance, float yTolerance, Angle angleTolerance, Angle curvatureTolerance ) { assert(angleTolerance<=Angle(180,Angle::DEGREE)); // +-180˚ covers everything, more would cause duplicate results (because the generated regions will overlap) assert(curvatureTolerance<=Angle(180,Angle::DEGREE)); int NORMAL_DIM = 2; // index of the normal orientation angle in the region bounds arrays int CURVATURE_DIM = 3; // index of the curvature orientation angle in the region bounds arrays double rLow[numDimensions], rHigh[numDimensions]; Angle lowerNormalBound = center->getAngularFeature(indexAngularFeature).normalize() - angleTolerance; Angle upperNormalBound = center->getAngularFeature(indexAngularFeature).normalize() + angleTolerance; Angle lowerCurvatureBound = center->curvature.normalize() - curvatureTolerance; Angle upperCurvatureBound = center->curvature.normalize() + curvatureTolerance; // location is unproblematic, no modulo here rLow[0] = center->x - xTolerance; rLow[1] = center->y - yTolerance; rHigh[0] = center->x + xTolerance; rHigh[1] = center->y + yTolerance; // SPLIT RANGES FOR MODULO BEHAVIOR OF ANGLES vector<SpatialIndex::Region> regions; // central region rLow[NORMAL_DIM] = std::max(0.f, lowerNormalBound.degree()); rHigh[NORMAL_DIM] = std::min(360.f, upperNormalBound.degree()); rLow[CURVATURE_DIM] = std::max(0.f, lowerCurvatureBound.degree()); rHigh[CURVATURE_DIM] = std::min(360.f, upperCurvatureBound.degree()); regions.push_back(SpatialIndex::Region(rLow, rHigh, numDimensions)); // normal orientation overshoot if(upperNormalBound.degree() > 360){ // 0 to normalize(upperNormal) in normal dimension rLow[NORMAL_DIM] = 0; rHigh[NORMAL_DIM] = upperNormalBound.normalize().degree(); rLow[CURVATURE_DIM] = std::max(0.f, lowerCurvatureBound.degree()); // clip the rest rHigh[CURVATURE_DIM] = std::min(360.f, upperCurvatureBound.degree()); regions.push_back(SpatialIndex::Region(rLow, rHigh, numDimensions)); } // normal orientation undershoot if(lowerNormalBound.degree() < 0){ // normalize(lowerNormal) to 360 in normal dimension rLow[NORMAL_DIM] = lowerNormalBound.normalize().degree(); rHigh[NORMAL_DIM] = 360; rLow[CURVATURE_DIM] = std::max(0.f, lowerCurvatureBound.degree()); // clip the rest rHigh[CURVATURE_DIM] = std::min(360.f, upperCurvatureBound.degree()); regions.push_back(SpatialIndex::Region(rLow, rHigh, numDimensions)); } // curvature orientation overshoot if(upperCurvatureBound.degree() > 360){ // 0 to normalize(lowerCurvature) in curvature dimension rLow[CURVATURE_DIM] = 0; rHigh[CURVATURE_DIM] = upperCurvatureBound.normalize().degree(); rLow[NORMAL_DIM] = std::max(0.f, lowerNormalBound.degree()); // clip the rest rHigh[NORMAL_DIM] = std::min(360.f, upperNormalBound.degree()); regions.push_back(SpatialIndex::Region(rLow, rHigh, numDimensions)); } // curvature orientation undershoot if(lowerCurvatureBound.degree() < 0){ // normalize(lowerCurvature) to 360 in curvature dimension rLow[CURVATURE_DIM] = lowerCurvatureBound.normalize().degree(); rHigh[CURVATURE_DIM] = 360; rLow[NORMAL_DIM] = std::max(0.f, lowerNormalBound.degree()); // clip the rest rHigh[NORMAL_DIM] = std::min(360.f, upperNormalBound.degree()); regions.push_back(SpatialIndex::Region(rLow, rHigh, numDimensions)); } // combined overshoot if(upperNormalBound.degree() > 360 && upperCurvatureBound.degree() > 360){ // 0 to normalize(upperCurvature) in curvature dimension // 0 to normalize(upperNormal) in normal dimension rLow[NORMAL_DIM] = 0; rHigh[NORMAL_DIM] = upperNormalBound.normalize().degree(); rLow[CURVATURE_DIM] = 0; rHigh[CURVATURE_DIM] = upperCurvatureBound.normalize().degree(); regions.push_back(SpatialIndex::Region(rLow, rHigh, numDimensions)); } // combined undershoot if(lowerNormalBound.degree() < 0 && lowerCurvatureBound.degree() < 0){ // normalize(lowerNormal) to 360 in normal dimension // normalize(lowerCurvature) to 360 in curvature dimension rLow[NORMAL_DIM] = lowerNormalBound.normalize().degree(); rHigh[NORMAL_DIM] = 360; rLow[CURVATURE_DIM] = lowerCurvatureBound.normalize().degree(); rHigh[CURVATURE_DIM] = 360; regions.push_back(SpatialIndex::Region(rLow, rHigh, numDimensions)); } // QUERY ALL REGIONS AND CONCAT RESULTS vector<ContourPointIdx> *result = new vector<ContourPointIdx>(); for (std::vector<SpatialIndex::Region>::iterator r = regions.begin(); r != regions.end(); ++r) { CollectIndicesVisitor cv(this); tree->intersectsWithQuery(*r, cv); for (vector<ContourPointIdx>::iterator it = cv.result.begin(); it != cv.result.end(); ++it) result->push_back(*it); } return *result; }