MultiArray<2, float > FieldAlgorithms::matchGradients(MultiArray<2, TinyVector<float, 2> > &imageGradients, MultiArray<2, TinyVector<float, 2> > &mask) { MultiArray<2, float > dest(imageGradients.shape()); dest = 0; //to make sure, that the mask is always fully within the image, consider the mask shape int diff = (mask.width() -1) / 2; for (int x = diff; x + diff < imageGradients.width(); x ++) { for (int y = diff; y + diff < imageGradients.height(); y++) { //The masks center is at point x,y now //Every vector of the image currently 'covered' by the mask, is compared to its corresponding vector in the mask. float vals = 0; for (int xM = 0; xM < mask.width(); xM++) { for (int yM = 0; yM < mask.height(); yM++) { TinyVector<float, 2> imageVal = imageGradients((x - diff) + xM, (y - diff) + yM); TinyVector<float, 2> maskVal = mask(xM, yM); vals += compareVectors(imageVal, maskVal); } } int res = vals / (mask.size()); dest(x,y) = res; } } return dest; };
Shape2 FieldAlgorithms::localizeByFollowingLocalMaxima(const MultiArray<2, float> &image, Shape2 current) { //Open viewBox of image with center at current int upperLeftX = current[0] - ((image.width() / 10) / 2); upperLeftX = upperLeftX > -1 ? upperLeftX : 0; int upperLeftY = current[1] - ((image.height() / 10) / 2); upperLeftY = upperLeftY > -1 ? upperLeftY : 0; Shape2 upperLeft(upperLeftX, upperLeftY); int lowerRightX = current[0] + ((image.width() / 10) / 2); lowerRightX = lowerRightX < image.width() ? lowerRightX : image.width() -1; int lowerRightY = current[1] + ((image.height() / 10) / 2); lowerRightY = lowerRightY < image.height() ? lowerRightY : image.height() -1; Shape2 lowerRight(lowerRightX, lowerRightY); MultiArrayView<2, float> box = image.subarray(upperLeft, lowerRight); //3: get local max of view as next int maxIndex = argMax(box); if (maxIndex == -1) { std::cout << "Something went wrong: argMax returned -1"; return current; } Shape2 max(box.scanOrderIndexToCoordinate(maxIndex)); Shape2 next(upperLeftX + max[0], upperLeftY + max[1]); if (next == current) { return next; } return localizeByFollowingLocalMaxima(image, next); }
Fields FieldAlgorithms::fieldsByLaplasian(MultiArray<2, float> & image) { MultiArray<2, float> valley(image.shape()); Pyramid pyramid(image); for (int i = 3; i > 0; i--) { MultiArray<2, float> resized(pyramid.get(i)); MultiArray<2, float> tmpArr(resized.shape()); laplacianOfGaussianMultiArray(resized, tmpArr, 1.0); valley += pyramid.toOriginalSize(tmpArr); } MultiArray<2, float> peak = valley * -1; //remove DC component float thrhld = valley[argMax(valley)] * 0.3; threshold(valley, valley, thrhld); thrhld = peak[argMax(peak)] * 0.3; threshold(peak, peak, thrhld); //Edge as Gradients MultiArray<2, float> edgeField(image.shape()); gaussianGradientMagnitude(image, edgeField, 1.0); //Localize std::vector<Shape2> valleyLocals(localizePOI(image)); //Result as Field Object Fields fields(valley, valleyLocals, peak, edgeField, image); //A heuristic initialization of the localization, as a priori known position Shape2 nextToIris = Shape2(image.width() / 2, image.height() / 2); fields.specializedIrisValley = localizeByFollowingLocalMaxima(image, nextToIris); return fields; }
Fields FieldAlgorithms::fieldsByGradientPattern(MultiArray<2, float> & image) { //Get Masks for Valley and Peak //not efficient, but can be scaled easly vigra::ImageImportInfo valleyInfo("../images/valleyMask.png"); MultiArray<2, float> valleyArray(valleyInfo.shape()); importImage(valleyInfo, valleyArray); MultiArray<2, float > valleyMask(9,9); resizeImageNoInterpolation(valleyArray, valleyMask); vigra::ImageImportInfo peakInfo("../images/peakMask.png"); MultiArray<2, float> peakArray(peakInfo.shape()); importImage(peakInfo, peakArray); MultiArray<2, float > peakMask(9,9); resizeImageNoInterpolation(peakArray, peakMask); Pyramid pyramid(image); MultiArray<2, float> valleyField(image.shape()); MultiArray<2, float> peakField(image.shape()); //go 3 octaves for (int i = 3; i > 0; i--) { MultiArray<2, float> resized(pyramid.get(i)); MultiArray<2, float> tmpArr = morphologyByGradientPattern(resized, valleyMask); valleyField += pyramid.toOriginalSize(tmpArr); tmpArr = morphologyByGradientPattern(resized, peakMask); peakField += pyramid.toOriginalSize(tmpArr); } //Edge as Gradients MultiArray<2, float> edgeField(image.shape()); gaussianGradientMagnitude(image, edgeField, 1.0); //Localize, smooth for increased range of interaction (following local maxima) MultiArray<2, float> smoothed(valleyField.shape()); gaussianSmoothMultiArray(valleyField, smoothed, 6.0); std::vector<Shape2> valleyLocals(localizePOI(smoothed)); //Result as Field Object Fields fields(valleyField, valleyLocals, peakField, edgeField, image); //A heuristic initialization of the localization, as a priori known position Shape2 nextToIris = Shape2(image.width() / 2 + 10, image.height() / 2); fields.specializedIrisValley = Shape2(image.width() / 2 + 10, image.height() / 2 + 15);//localizeByFollowingLocalMaxima(valleyField, nextToIris); return fields; };
//Calculates the fit for all radii std::vector<MultiArray<2,float>> Deformation::getFit(MultiArray<2, int> &distanceToCenter) { int length = distanceToCenter.width(); MultiArray<2,float> resEdge(Shape2(length, 1)); MultiArray<2,float> resValley(Shape2(length, 1)); MultiArray<2,float> resBoth(Shape2(length, 1)); for (int radius = 1; radius < distanceToCenter.width() / 2; radius++) { RadiusResult radi = getValueForRadius(distanceToCenter, radius); resValley[radius] = radi.valley; resBoth[radius] = radi.getValue(); resEdge[radius] = radi.edge; } std::vector<MultiArray<2,float>>result(3); result[0] = resEdge; result[1] = resValley; result[2] = resBoth; return result; }
RadiusResult Deformation::getRadiusRecursivly(MultiArray<2, int> &distanceToCenter, RadiusResult &one, RadiusResult &two, float temperature) { if (temperature < 1) { return one; } if (one.radius == two.radius) { one.radius++; } float derivative = (one.getValue() - two.getValue()) / (one.radius - two.radius); derivative = derivative < 0 && derivative > -1 ? -1 : derivative > 0 && derivative < 1 ? 1 : derivative; int nextRadius = (one.radius + (derivative * temperature)); //TODO: Metropolis //prevent values larger than the image nextRadius = nextRadius < 0 ? distanceToCenter.width() / 2 - nextRadius : nextRadius; nextRadius = nextRadius % (distanceToCenter.width() / 2); RadiusResult next = getValueForRadius(distanceToCenter, nextRadius); return getRadiusRecursivly(distanceToCenter, next, one, temperature * 0.95); };
std::vector<Shape2> FieldAlgorithms::localizePOI(MultiArray<2, float> &image) { std::vector<Shape2> pois(1); for (int i = 0; i < pois.size(); i++) { int v1 = std::rand() % image.size() -1; //int maxIndex = argMax(box); //Shape2 max(box.scanOrderIndexToCoordinate(maxIndex)); //image.scanOrderIndexToCoordinate(v1) Shape2 poi = localizeByFollowingLocalMaxima(image, Shape2(image.width()/2, image.height()/2)); pois[i] = poi; } return pois; }
void Deformation::drawFunctions(MultiArray<2, int> &distanceToCenter) { std::vector<MultiArray<2,float>> functions = getFit(distanceToCenter); MultiArray<2,float> resEdge(distanceToCenter.shape()); MultiArray<2,float> resValley(distanceToCenter.shape()); MultiArray<2,float> resBoth(distanceToCenter.shape()); for (int i = 0; i<distanceToCenter.width() / 2;i++) { int yEdge = functions[0][i] > distanceToCenter.height() ? distanceToCenter.height() -1 : (distanceToCenter.height() - (functions[0][i] -1)); int yValley = functions[1][i] > distanceToCenter.height() ? distanceToCenter.height() -1 : (distanceToCenter.height() - (functions[1][i] -1)); int yBoth = functions[2][i] > distanceToCenter.height() ? distanceToCenter.height() -1 : (distanceToCenter.height() - (functions[2][i] -1)); resEdge(i, yEdge) = 1; resValley(i, yValley) = 1; resBoth(i, yBoth) = 1; } exportImage(resEdge,"./../images/results/edgeFunction.png"); exportImage(resValley,"./../images/results/valleyFunction.png"); exportImage(resBoth ,"./../images/results/bothFunction.png"); std::cout << "\n expected Radius: "; int rad = argMax(functions[2]); std::cout << rad; functions[2][rad] = 0; rad = argMax(functions[2]); std::cout << "\n next best Radius: "; std::cout << rad; functions[2][rad] = 0; rad = argMax(functions[2]); std::cout << "\n next best Radius: "; std::cout << rad; functions[2][rad] = 0; rad = argMax(functions[2]); std::cout << "\n next best Radius: "; std::cout << rad; functions[2][rad] = 0; rad = argMax(functions[2]); std::cout << "\n"; }