public static bool IsBitmapEquel(string BaseImageFileName, string TargetImageFileName, string ResultFileName) { MagickImage magickBaseImg = new MagickImage(BaseImageFileName); MagickImage magickTargetImg = new MagickImage(TargetImageFileName); var diffImg = new MagickImage(); double percentageDifference; ErrorMetric EM = ErrorMetric.Fuzz; // Fuzz !? percentageDifference = magickBaseImg.Compare(magickTargetImg, EM, diffImg, Channels.Red); percentageDifference = percentageDifference * 100; percentageDifference = Math.Round(percentageDifference, 2); TypeConverter tc = TypeDescriptor.GetConverter(typeof(Bitmap)); Bitmap ImgToSave = (Bitmap)tc.ConvertFrom(diffImg.ToByteArray()); ImgToSave.Save(ResultFileName); if (percentageDifference == 0) { return(true); } else { return(false); } }
/// <summary> /// Adds two error metrics. /// </summary> /// <param name="value1">The source error metric.</param> /// <param name="value2">The source error metric.</param> /// <returns>The result error metric.</returns> public static ErrorMetric Add(ref ErrorMetric value1, ref ErrorMetric value2) { ErrorMetric result; Add(ref value1, ref value2, out result); return(result); }
public static bool IsBitmapEquel(string BaseImageFileName, string TargetImageFileName, string ResultFileName) { MagickImage magickBaseImg = new MagickImage(BaseImageFileName); MagickImage magickTargetImg = new MagickImage(TargetImageFileName); var diffImg = new MagickImage(); double percentageDifference; ErrorMetric EM = ErrorMetric.Fuzz; // Fuzz !? percentageDifference = magickBaseImg.Compare(magickTargetImg, EM, diffImg, Channels.Red); percentageDifference = percentageDifference * 100; percentageDifference = Math.Round(percentageDifference, 2); Bitmap ImgToSave = diffImg.ToBitmap(); ImgToSave.Save(ResultFileName); if (percentageDifference == 0) { return(true); } else { return(false); } }
public void Test_ComputeError_WithNormalization() { CorrespondenceCollection correspondences = new CorrespondenceCollection(); correspondences.Add(new Correspondence( staticPoint: new Point(new Vector3(1, 2, 3)), modelPoint: new Point(new Vector3(2, 4, 4)) )); correspondences.Add(new Correspondence( staticPoint: new Point(new Vector3(2, 3, 4)), modelPoint: new Point(new Vector3(4, 4, 3)) )); errorMetric = new ErrorMetric( new ErrorMetric.Configuration( distanceMetric: DistanceMetrics.SquaredEuclidean, aggregationMethod: AggregationMethods.Sum, normalizePoints: true ) ); float expected = 1.3333333333f; float actual = errorMetric.ComputeError(correspondences, null, null); Assert.That(actual, Is.EqualTo(expected).Within(tolerance)); }
public static double CompareV2(this MagickImage self, MagickImage oldImg, ErrorMetric errorMetric, out MagickImage imgWithDifferences) { // Check if both images have the same size: bool isNewImageSameSizeAsOldImage = oldImg.Width == self.Width && oldImg.Height == self.Height; if (!isNewImageSameSizeAsOldImage) { var diffSizesWarn = $"Different sizes: OldImage=({oldImg.Width}X{oldImg.Height}) but NewImage=({self.Width}X{self.Height})"; bool isNewImageAspectRatioSameAsOldImage = self.GetAspectRatio() == oldImg.GetAspectRatio(); if (isNewImageAspectRatioSameAsOldImage) { Log.w(diffSizesWarn); // If aspect ratio matches, resize both images to same size: var minWidth = Math.Min(oldImg.Width, self.Width); var minHeight = Math.Min(oldImg.Height, self.Height); oldImg.Resize(minWidth, minHeight); self.Resize(minWidth, minHeight); } else // Missmatch in image sizes cant be fixed, abort: { throw new ArgumentException("Can't compare! " + diffSizesWarn); } } AssertV2.AreEqual(oldImg.Width, self.Width, "RegressionImage.Width"); AssertV2.AreEqual(oldImg.Height, self.Height, "RegressionImage.Height"); //return oldImg.Compare(self, out imgWithDifferences); imgWithDifferences = new MagickImage(); return(oldImg.Compare(self, new CompareSettings() { Metric = errorMetric }, imgWithDifferences)); }
/// <summary> /// Subtracts two error metrics. /// </summary> /// <param name="value1">The source error metric.</param> /// <param name="value2">The source error metric.</param> /// <returns>The result error metric.</returns> public static ErrorMetric Subtract(ref ErrorMetric value1, ref ErrorMetric value2) { ErrorMetric result; Subtract(ref value1, ref value2, out result); return(result); }
public static void RegisterComparers(double threshold = .005, ErrorMetric metric = ErrorMetric.Fuzz) { RegisterComparer(threshold, metric, "png", MagickFormat.Png); RegisterComparer(threshold, metric, "jpg", MagickFormat.Jpg); RegisterComparer(threshold, metric, "bmp", MagickFormat.Bmp); RegisterComparer(threshold, metric, "tiff", MagickFormat.Tiff); }
public int CompareImage(string name, ErrorMetric errorMetric, int imageWriteTreshold, string rootUrl1, string rootUrl2) { var activeImage = new MagickImage(ImagePath(rootUrl2, name)); var approvedImage = new MagickImage(ImagePath(rootUrl1, name)); //Assert.IsNotNull(activeImage); //Assert.IsNotNull(approvedImage); try { using (var delta = new MagickImage()) { var compareResult = Convert.ToInt32(Math.Round(activeImage.Compare(approvedImage, errorMetric, delta) * 100)); if (compareResult > imageWriteTreshold) { delta.Write(DeltaImagePath(name)); } return(Convert.ToInt32(compareResult)); } } catch (Exception ex) { LastException = ex; return(0); } }
/// <summary> /// Computes edge cost for triangle. /// </summary> /// <param name="t">The triangle.</param> private void ComputeEdgeCost(Triangle t) { ErrorMetric E12 = (ErrorMetric)t.m_Edge12.Tag; ErrorMetric E23 = (ErrorMetric)t.m_Edge23.Tag; ErrorMetric E31 = (ErrorMetric)t.m_Edge31.Tag; Vector3 V1; Vector3 V2; Vector3 V3; ErrorMetric.ComputeNewPosition(ref E12, out V1); ErrorMetric.ComputeNewPosition(ref E23, out V2); ErrorMetric.ComputeNewPosition(ref E31, out V3); E12.ProposedPoint = V1; E23.ProposedPoint = V2; E31.ProposedPoint = V3; WeightPolicy policy = (WeightPolicy.MiddlePoint | WeightPolicy.AverageTriangleArea | WeightPolicy.Optmized); OptimizeEdgeTarget(ref t.m_Vertex1, ref t.m_Vertex2, ref t.m_Edge12, policy); OptimizeEdgeTarget(ref t.m_Vertex2, ref t.m_Vertex3, ref t.m_Edge23, policy); OptimizeEdgeTarget(ref t.m_Vertex3, ref t.m_Vertex1, ref t.m_Edge31, policy); t.Cost = Math.Min(t.Edge12.Cost, Math.Min(t.Edge23.Cost, t.Edge31.Cost)); }
void IVisualAnalyzer.Compare() { MagickImage magickBaseImg = new MagickImage(mAct.baseImage); MagickImage magickTargetImg = new MagickImage(mAct.targetImage); var diffImg = new MagickImage(); double percentageDifference; // TODO: add combo with list of options for user to choose the Error Matic and Cahnnels ActInputValue AIV = mAct.GetOrCreateInputParam(ActVisualTesting.Fields.ErrorMetric); //TODO: fix me - removed hard code //caused build problem on build machine so temp fix for now ErrorMetric EM = ErrorMetric.Fuzz; percentageDifference = magickBaseImg.Compare(magickTargetImg, EM, diffImg, Channels.Red); percentageDifference = percentageDifference * 100; percentageDifference = Math.Round(percentageDifference, 2); Bitmap ImgToSave = diffImg.ToBitmap(); mAct.CompareResult = ImgToSave; mAct.AddOrUpdateReturnParamActual("Percentage Difference", percentageDifference + ""); mAct.AddScreenShot(ImgToSave, "Compare Result"); }
/// <summary> /// Transforms error metric by other error metric. /// </summary> /// <param name="m">The other error metric.</param> public void Transform(ref ErrorMetric m) { Matrix Q = m_Matrix; Matrix Pa = m.m_Matrix; Q = Pa * Q * Pa; m_Matrix = Q; }
public void Init() { ErrorMetric.Configuration configuration = new ErrorMetric.Configuration( distanceMetric: DistanceMetrics.SquaredEuclidean, aggregationMethod: AggregationMethods.Sum, normalizePoints: false ); errorMetric = new ErrorMetric(configuration); }
private static unsafe extern int Encode(float[] a_pafSourceRGBA, uint a_uiSourceWidth, uint a_uiSourceHeight, Format a_format, ErrorMetric a_eErrMetric, float a_fEffort, uint a_uiJobs, uint a_uimaxJobs, out char *a_ppaucEncodingBits, out uint a_puiEncodingBitsBytes, out uint a_puiExtendedWidth, out uint a_puiExtendedHeight, out uint a_piEncodingTime_ms, bool a_bVerboseOutput = false);
/// <summary> /// Computes error metric for specified vertex. /// </summary> /// <param name="vertex">The source vertex.</param> private void ComputeErrorMetricForVertex(Vertex vertex) { ErrorMetric Q = ErrorMetric.Empty; foreach (var t in vertex.Triangles) { ErrorMetric K = (ErrorMetric)t.Tag; ErrorMetric.Add(ref Q, ref K, out Q); } vertex.Tag = (object)Q; }
/// <summary> Compares a current and previous version of an image and returns a diff image if they differ </summary> /// <param name="self">The current version of the image </param> /// <param name="imgFile"> The file where the previous version of the image is stored in </param> /// <param name="maxAllowedDiff"> A good value to start testing with would be e.g. 0.0005 </param> /// <returns> null if the images do not differ, a diff image otherwise </returns> public static FileEntry Compare(this MagickImage self, FileEntry imgFile, ErrorMetric errorMetric, double maxAllowedDiff) { using (MagickImage oldImg = new MagickImage()) { oldImg.LoadFromFileEntry(imgFile); double diffValue = self.CompareV2(oldImg, errorMetric, out MagickImage imgWithDifferences); var diffDetected = diffValue > maxAllowedDiff; // Log.d($"Visual difference of current scene VS image '{imgFile.Name}' is: {diffValue} vs {maxAllowedDiff} (max allowed diff)"); FileEntry diffFile = imgFile.Parent.GetChild(imgFile.NameWithoutExtension + ".diff" + imgFile.ExtensionWithDot); imgWithDifferences.SaveToFileEntry(diffFile); imgWithDifferences.Dispose(); return(diffDetected ? diffFile : null); } }
/// <summary> /// Optimizes edge target. /// </summary> /// <param name="v1">The source edge vertex.</param> /// <param name="v2">The target edge vertex.</param> /// <param name="edge">The edge additional params.</param> /// <param name="policy">The used policy.</param> private void OptimizeEdgeTarget(ref Vertex v1, ref Vertex v2, ref Triangle.Edge edge, WeightPolicy policy) { ErrorMetric Q = (ErrorMetric)edge.Tag; double min_cost = double.MaxValue; Vector3 best; if (policy.HasFlag(WeightPolicy.Optmized) && Q.Optimize(out best)) { Q.ProposedPoint = best; min_cost = Q.VertexError(best); } else { double min1 = Q.VertexError(v1.Position); double min2 = Q.VertexError(v2.Position); if (min1 < min2) { min_cost = min1; best = v1.Position; } else { min_cost = min2; best = v2.Position; } if (policy.HasFlag(WeightPolicy.MiddlePoint)) { Vector3 middle = Vector3Extension.Mean(v1.Position, v2.Position); double cost_middle = Q.VertexError(middle); if (cost_middle < min_cost) { min_cost = cost_middle; best = middle; } } } if (policy.HasFlag(WeightPolicy.AverageTriangleArea)) { min_cost /= Q.Area; } edge.Cost = -min_cost; Q.ProposedPoint = best; edge.Tag = (object)Q; }
/// <summary> /// Compute error metric for edges in triangle. /// </summary> /// <param name="t">The triangle.</param> private void ComputeErrorMetricForEdges(Triangle t) { ErrorMetric V1 = (ErrorMetric)t.Vertex1.Tag; ErrorMetric V2 = (ErrorMetric)t.Vertex2.Tag; ErrorMetric V3 = (ErrorMetric)t.Vertex3.Tag; ErrorMetric E12 = ErrorMetric.Empty; ErrorMetric E23 = ErrorMetric.Empty; ErrorMetric E31 = ErrorMetric.Empty; ErrorMetric.Add(ref V1, ref V2, out E12); ErrorMetric.Add(ref V2, ref V3, out E23); ErrorMetric.Add(ref V3, ref V1, out E31); t.Edge12.Tag = E12; t.Edge23.Tag = E23; t.Edge31.Tag = E31; }
private void btnImageCompare_Click(object sender, EventArgs e) { string orgImagePath = lblImage1Path.Text; string dupImagePath = lblImage2Path.Text; bool isFirstImageEmpty = string.IsNullOrWhiteSpace(orgImagePath); bool isSecondImageEmpty = string.IsNullOrWhiteSpace(dupImagePath); if (isFirstImageEmpty || isSecondImageEmpty) { MessageBox.Show("Please select images before compare"); } bool ispHashSelected = cbCompareAlgorithm.Text == "pHash"; bool isBhattacharyyaSelected = cbCompareAlgorithm.Text == "Bhattacharyya"; if (ispHashSelected) { var percentage = ImageHashing.Similarity(orgImagePath, dupImagePath); percentage = Math.Round(percentage, 3); txtPerDiff.Text = percentage.ToString(); } else if (isBhattacharyyaSelected) { Image img1 = Image.FromFile(orgImagePath); Image img2 = Image.FromFile(dupImagePath); var percentage = Bhattacharyya.BhattacharyyaDifference(img1, img2); percentage = percentage * 100; percentage = Math.Round(percentage, 3); txtPerDiff.Text = percentage.ToString(); } else { int imageAlgoIndex = cbCompareAlgorithm.SelectedIndex; ErrorMetric imageAlgo = (ErrorMetric)imageAlgoIndex; MagickImage orgImage = new MagickImage(orgImagePath); MagickImage dupImage = new MagickImage(dupImagePath); var percentage = orgImage.Compare(dupImage, imageAlgo); txtPerDiff.Text = percentage.ToString(); orgImage.Dispose(); dupImage.Dispose(); } }
public void Test_Equals_Equal() { ErrorMetric thisMetric = new ErrorMetric( new ErrorMetric.Configuration( distanceMetric: DistanceMetrics.PointToPlane, normalizePoints: true, aggregationMethod: AggregationMethods.Sum ) ); ErrorMetric otherMetric = new ErrorMetric( new ErrorMetric.Configuration( distanceMetric: DistanceMetrics.PointToPlane, normalizePoints: true, aggregationMethod: AggregationMethods.Sum ) ); Assert.IsTrue(thisMetric.Equals(otherMetric)); Assert.IsTrue(otherMetric.Equals(thisMetric)); Assert.AreEqual(thisMetric.GetHashCode(), otherMetric.GetHashCode()); }
public CWatcher( CWatchImage[] cWatchImages, string name, WatcherType watcherType, ColorSpace colorSpace, int channel, bool equalize, ErrorMetric errorMetric ) { Name = name; WatcherType = watcherType; ColorSpace = colorSpace; Channel = channel; Equalize = equalize; ErrorMetric = errorMetric; CWatchImages = cWatchImages; IsStandard = WatcherType.Equals(WatcherType.Standard); IsDuplicateFrame = WatcherType.Equals(WatcherType.DuplicateFrame); }
/// <summary> /// Computes new proposed position using specified error metric. /// </summary> /// <param name="metric">The error metric.</param> /// <returns>The proposed position.</returns> public static void ComputeNewPosition(ref ErrorMetric metric, out Vector3 proposedPosition) { // Replace bottom row: Matrix m = metric.m_Matrix; m.M41 = m.M42 = m.M43 = 0.0f; m.M44 = 1.0f; // Invert matrix. //Matrix.Transpose(ref m, out m); Matrix.Invert(ref m, out m); // Vector x Matrix Vector4 newPosition; MatrixExtension.Multiply(ref m, ref m_Wzero, out newPosition); proposedPosition = new Vector3( newPosition.X, newPosition.Y, newPosition.Z); }
public static double CompareV2(this MagickImage self, MagickImage oldImg, ErrorMetric errorMetric, out MagickImage imgWithDifferences) { AssertV2.AreEqual(oldImg.Width, self.Width, "RegressionImage.Width"); AssertV2.AreEqual(oldImg.Height, self.Height, "RegressionImage.Height"); // Check if both images have the same size: if (oldImg.Width != self.Width || oldImg.Height != self.Height) { if (self.GetAspectRatio() == oldImg.GetAspectRatio()) { // If aspect ratio matches, resize both images to same size: var minWidth = Math.Min(oldImg.Width, self.Width); var minHeight = Math.Min(oldImg.Height, self.Height); oldImg.Resize(minWidth, minHeight); self.Resize(minWidth, minHeight); } } //return oldImg.Compare(self, out imgWithDifferences); imgWithDifferences = new MagickImage(); return(oldImg.Compare(self, new CompareSettings() { Metric = errorMetric }, imgWithDifferences)); }
/// <summary> /// Computes new proposed position using specified error metric. /// </summary> /// <param name="metric">The error metric.</param> /// <returns>The proposed position.</returns> public static Vector3 ComputeNewPosition(ref ErrorMetric metric) { // Replace bottom row: Matrix m = metric.m_Matrix; m.M41 = m.M42 = m.M43 = 0.0f; m.M44 = 1.0f; // Invert matrix. //Matrix.Transpose(ref m, out m); Matrix.Invert(ref m, out m); // Vector x Matrix Vector4 newPosition; MatrixExtension.Multiply(ref m, ref m_Wzero, out newPosition); return new Vector3( newPosition.X, newPosition.Y, newPosition.Z); }
public float ComputeError(CorrespondenceCollection correspondences, Transform originalTransform, Transform newTransform) { return(ErrorMetric.Wheeler().ComputeError(correspondences, originalTransform, newTransform)); }
/// <summary> /// Adds two error metrics. /// </summary> /// <param name="value1">The source error metric.</param> /// <param name="value2">The source error metric.</param> /// <param name="result">The result error metric.</param> public static void Add(ref ErrorMetric value1, ref ErrorMetric value2, out ErrorMetric result) { result = new ErrorMetric(); result.m_Area = value1.m_Area + value2.m_Area; result.m_Matrix = value1.m_Matrix + value2.m_Matrix; }
public LowTransformFinder() { this.errorMetric = ErrorMetric.Low(); }
/// <summary> /// Subtracts two error metrics. /// </summary> /// <param name="value1">The source error metric.</param> /// <param name="value2">The source error metric.</param> /// <param name="result">The result error metric.</param> public static void Subtract(ref ErrorMetric value1, ref ErrorMetric value2, out ErrorMetric result) { result = new ErrorMetric(); result.m_Area = value1.m_Area - value2.m_Area; result.m_Matrix = value1.m_Matrix - value2.m_Matrix; }
public static void FindDifferenceBetweenImages(MagickImage etalonImage, MagickImage newImage, ErrorMetric metric, string differenceImageSavePath) { using (MagickImage etalon = etalonImage) using (MagickImage newI = newImage) using (MagickImage diffImage = new MagickImage()) { etalon.Compare(newI, metric, diffImage); diffImage.Write(differenceImageSavePath); } }
public float ComputeTerminationError(CorrespondenceCollection correspondences, Transform originalTransform, Transform currentTransform) { return(ErrorMetric.Wheeler().ComputeTerminationError(correspondences, originalTransform, currentTransform)); }
public void Remesh(ref Mesh mesh, IProgressListener progress = null) { var triangles = mesh.Triangles; var vertices = mesh.Vertices; // Compute K matrices for initial triangles. foreach (var t in triangles) { t.UpdateGeometricData(); t.Tag = new ErrorMetric(t); } // Compute Q for intiial vertices. foreach (var v in vertices) { ComputeErrorMetricForVertex(v); } // Compute initial edge QEM-s foreach (var t in triangles) { ComputeErrorMetricForEdges(t); } foreach (var t in triangles) { ComputeEdgeCost(t); } foreach (var v in vertices) { v.Cost = 0.0; foreach (var t in v.Triangles) { v.Cost += Math.Max(Math.Max(t.Edge12.Cost, t.Edge23.Cost), t.Edge31.Cost); } } // Compute number of triangles after we stop int toRemove = (int)((m_Removed) * triangles.Count); int triangleLimit = triangles.Count - toRemove; #if TRACE_NANS int nansCount = 0; #endif int index = 0; for (int i = 0; (i < m_Removed) && (2 * m_Removed < triangles.Count); i += 2) { Vertex v1, v2; Triangle.Edge edge; if (SearchBestCandidate(ref mesh, out v1, out v2, out edge)) { if (edge != null) { ErrorMetric em = (ErrorMetric)edge.Tag; Vector3 v = em.ProposedPoint; #if false if (v.IsNaN()) { #if TRACE_NANS ++nansCount; #endif v = Vector3Extension.Mean(v1.Position, v2.Position); } #endif if (mesh.JoinVertices(v1, v2, v)) { // V1, since v2 is removed from now. UpdateVertexNeighbors(v1); } progress.OnProgress(index, toRemove); index += 2; } else { Trace.WriteLine("If you see this message more than once per second, I can't find any matching edge"); } } } #if TRACE_NANS Trace.WriteLine(string.Format("NaNs count: {0}", nansCount)); #endif }
/// <summary> /// Adds two error metrics. /// </summary> /// <param name="value1">The source error metric.</param> /// <param name="value2">The source error metric.</param> /// <returns>The result error metric.</returns> public static ErrorMetric Add(ref ErrorMetric value1, ref ErrorMetric value2) { ErrorMetric result; Add(ref value1, ref value2, out result); return result; }
public float ComputeInitialError(CorrespondenceCollection correspondences) { return(ErrorMetric.Wheeler().ComputeInitialError(correspondences)); }
/// <summary> /// Subtracts two error metrics. /// </summary> /// <param name="value1">The source error metric.</param> /// <param name="value2">The source error metric.</param> /// <returns>The result error metric.</returns> public static ErrorMetric Subtract(ref ErrorMetric value1, ref ErrorMetric value2) { ErrorMetric result; Subtract(ref value1, ref value2, out result); return result; }
public IntPtr SubImageSearch(MagickImage reference, ErrorMetric metric, double similarityThreshold, out MagickRectangle offset, out double similarityMetric) { using (INativeInstance offsetNative = MagickRectangle.CreateInstance()) { IntPtr offsetNativeOut = offsetNative.Instance; IntPtr exception = IntPtr.Zero; IntPtr result; #if ANYCPU if (NativeLibrary.Is64Bit) #endif #if WIN64 || ANYCPU result = NativeMethods.X64.MagickImage_SubImageSearch(Instance, MagickImage.GetInstance(reference), (UIntPtr)metric, similarityThreshold, offsetNativeOut, out similarityMetric, out exception); #endif #if ANYCPU else #endif #if !WIN64 || ANYCPU result = NativeMethods.X86.MagickImage_SubImageSearch(Instance, MagickImage.GetInstance(reference), (UIntPtr)metric, similarityThreshold, offsetNativeOut, out similarityMetric, out exception); #endif offset = MagickRectangle.CreateInstance(offsetNative); CheckException(exception, result); return result; } }
public double CompareDistortion(MagickImage image, ErrorMetric metric, Channels channels) { IntPtr exception = IntPtr.Zero; double result; #if ANYCPU if (NativeLibrary.Is64Bit) #endif #if WIN64 || ANYCPU result = NativeMethods.X64.MagickImage_CompareDistortion(Instance, MagickImage.GetInstance(image), (UIntPtr)metric, (UIntPtr)channels, out exception); #endif #if ANYCPU else #endif #if !WIN64 || ANYCPU result = NativeMethods.X86.MagickImage_CompareDistortion(Instance, MagickImage.GetInstance(image), (UIntPtr)metric, (UIntPtr)channels, out exception); #endif CheckException(exception); return result; }