public AutoRotateAction() { this.Name = "AutoRotate"; this.Action = (input) => { this.Status = "Processing..."; var maxRotation = this.MaxRotationDegrees.DegToRad(); var clusterThreshold = this.ClusterThresholdDegrees.DegToRad(); var zeroRotation = this.searchFor == SearchForEnum.HorizontalLines ? 90.0 : 0.0; var canny = input.Canny(this.Threshold1, this.Threshold2, 3); // Apply Hough Lines. var lines = canny.HoughLines(this.HoughRho, this.HoughTheta, (int)this.HoughThreshold); var thetaValues = lines .Select(l => (double)l.Theta) .Where(t => t.DistanceToRad(zeroRotation, ignoreRotationDirection: true) < maxRotation); // Detect biggest cluster. var cluster = ClusterDetection1D.Detect(thetaValues, clusterThreshold); var(important, nonImportant) = lines.Split(line => cluster.Contains(line.Theta)); // Draw lines. Mat image; if (this.Debug) { if (input.Channels() == 1) { image = input.CvtColor(ColorConversionCodes.GRAY2BGR); input.Dispose(); } else { image = input; } foreach (var line in nonImportant) { line.Draw(image, Scalar.Red); } foreach (var line in important) { line.Draw(image, Scalar.Green); } } else { image = input; } // Rotate. var rotation = !cluster.Any() ? 0.0 : cluster.Average(); if (rotation != 0.0) { var origin = this.SearchFor == SearchForEnum.HorizontalLines ? 270.0 : 180.0; var transformMatrix = Cv2.GetRotationMatrix2D(new Point2f(input.Width / 2, input.Height / 2), origin + rotation.RadToDeg(), 1); var size = input.Size(); image = image.WarpAffine(transformMatrix, size); } this.Status = $"{lines.Length} lines detected ({important.Count} used to determine rotation of {rotation.RadToDeg():F1}°)"; return(image); }; }
public void DetectTest(double[] input, double[] expectedOutput) { var cluster = ClusterDetection1D.Detect(input, 0.1); cluster.Should().BeEquivalentTo(expectedOutput); }