コード例 #1
0
        private static int[] GreyScale(FramePixelData pixelData, int newWidth, int newHeight)
        {
            var resized = new int[newWidth * newHeight];

            var stepX = pixelData.Width / (float)newWidth;
            var stepY = pixelData.Height / (float)newHeight;

            for (var y = 0; y < newHeight; y++)
            {
                for (var x = 0; x < newWidth; x++)
                {
                    // We use a simple nearest neighbor sample as any blending
                    // would only serve to increase the differences between the images.

                    var sx = (int)(x * stepX);
                    var sy = (int)(y * stepY);
                    var si = sx + (sy * pixelData.Width);
                    var scolor = pixelData.Data[si];
                    
                    // Convert to a greyscale value which removes small
                    // color differences that the eye cannot spot.
                    var grayScale = (int)((scolor.R * 0.3) + (scolor.G * 0.59) + (scolor.B * 0.11));

                    var di = x + (y * newWidth);
                    resized[di] = grayScale;
                }
            }

            return resized;
        }
コード例 #2
0
        private static int[] GreyScale(FramePixelData pixelData, int newWidth, int newHeight)
        {
            var resized = new int[newWidth * newHeight];

            var stepX = pixelData.Width / (float)newWidth;
            var stepY = pixelData.Height / (float)newHeight;

            for (var y = 0; y < newHeight; y++)
            {
                for (var x = 0; x < newWidth; x++)
                {
                    // We use a simple nearest neighbor sample as any blending
                    // would only serve to increase the differences between the images.

                    var sx     = (int)(x * stepX);
                    var sy     = (int)(y * stepY);
                    var si     = sx + (sy * pixelData.Width);
                    var scolor = pixelData.Data[si];

                    // Convert to a greyscale value which removes small
                    // color differences that the eye cannot spot.
                    var grayScale = (int)((scolor.R * 0.3) + (scolor.G * 0.59) + (scolor.B * 0.11));

                    var di = x + (y * newWidth);
                    resized[di] = grayScale;
                }
            }

            return(resized);
        }
コード例 #3
0
		public float Compare (FramePixelData a, FramePixelData b)
		{
			int minWidth, maxWidth, minHeight, maxHeight;

			MathUtility.MinMax (a.Width, b.Width, out minWidth, out maxWidth);
			MathUtility.MinMax (a.Height, b.Height, out minHeight, out maxHeight);

			var rect = new System.Drawing.Rectangle (0, 0, minWidth, minHeight);

			long error = 0;

			int index = 0;
			for (int y = 0; y < rect.Height; ++y) {
				for (int x = 0; x < rect.Width; ++x) {
					error += Delta (a.Data [index], b.Data [index]);
					index++;
				}
			}

			// FIXME: To temporarily accommodate the differing
			//        resolutions of mobile platforms, we just
			//        ignore all non-overlapping pixels.  This
			//        is not ideal, but it's good enough for now.
			// Mark all out-of-bounds pixels as non-match.
			//error += PixelArgb.MaxDelta * ((maxWidth * maxHeight) - (minWidth * minHeight));

			var dissimilarity = ((float) error / (float) (PixelArgb.MaxDelta * minWidth * minHeight));

			// Project dissimilarity to a logarithmic scale.  The
			// difference between having zero pixels wrong and one
			// pixel wrong is more significant than the difference
			// betweeen 10,000 wrong and 10,001.
			return 1.0f - (float) Math.Pow (dissimilarity, 0.5);
		}
コード例 #4
0
        private void WriteDiff(FramePixelData capture, FramePixelData reference, string outputPath)
        {
            var diff = CreateDiff(capture, reference);

            Normalize(diff);
            diff.Save(outputPath);
        }
コード例 #5
0
        protected static void WriteFrameDiffs(
            IEnumerable <FrameComparisonResult> results, string directory)
        {
            try {
                Directory.CreateDirectory(directory);
            } catch (IOException) {
            }

            foreach (var result in results)
            {
                string diffFileName = string.Format(
                    "diff-{0}-{1}.png",
                    Path.GetFileNameWithoutExtension(result.ReferenceImagePath),
                    Path.GetFileNameWithoutExtension(result.CapturedImagePath));


                string diffOutputPath = Path.Combine(directory, diffFileName);

                var a    = FramePixelData.FromFile(result.ReferenceImagePath);
                var b    = FramePixelData.FromFile(result.CapturedImagePath);
                var diff = CreateDiff(a, b);
                Normalize(diff);
                diff.Save(diffOutputPath);
            }
        }
コード例 #6
0
 public FramePixelDataRetriever(FramePixelData source)
 {
     _loader           = source.Parent._loader;
     SopInstanceUid    = source.Parent.SopInstanceUid;
     TransferSyntaxUid = source.Parent.TransferSyntaxUid;
     _frameNumber      = source.FrameNumber;
 }
コード例 #7
0
        public float Compare(FramePixelData image, FramePixelData referenceImage)
        {
            // Conver the images down to a common sized greyscale image.
            var width  = Math.Min(image.Width, referenceImage.Width);
            var height = Math.Min(image.Height, referenceImage.Height);
            var img    = GreyScale(image, width, height);
            var imgRef = GreyScale(referenceImage, width, height);

            // Find the differences between the greyscale images.
            var absDiff = new int[width * height];

            for (var i = 0; i < absDiff.Length; i++)
            {
                absDiff[i] = Math.Abs(img[i] - imgRef[i]);
            }

            // Find all the differences over the threshold.
            const int threshold  = 3;
            var       diffPixels = 0;

            for (var i = 0; i < absDiff.Length; i++)
            {
                if (absDiff[i] > threshold)
                {
                    diffPixels++;
                }
            }

            // Calculate the difference percentage.
            var diff = diffPixels / (float)absDiff.Length;

            return(1.0f - diff);
        }
コード例 #8
0
        public float Compare(FramePixelData image, FramePixelData referenceImage)
		{        
            // Conver the images down to a common sized greyscale image.
            var width = Math.Min(image.Width, referenceImage.Width);
            var height = Math.Min(image.Height, referenceImage.Height);
            var img = GreyScale(image, width, height);
            var imgRef = GreyScale(referenceImage, width, height);

            // Find the differences between the greyscale images.
            var absDiff = new int[width * height];
            for (var i = 0; i < absDiff.Length; i++)
                absDiff[i] = Math.Abs(img[i] - imgRef[i]);

            // Find all the differences over the threshold.
		    const int threshold = 3;
            var diffPixels = 0;
            for (var i = 0; i < absDiff.Length; i++)
            {
                if (absDiff[i] > threshold) 
                    diffPixels++;
            }

            // Calculate the difference percentage.
            var diff = diffPixels / (float)absDiff.Length;
		    return 1.0f - diff;
		}
コード例 #9
0
 private static FramePixelData LoadOrCreateEmptyFramePixelData(string path)
 {
     try {
         return(FramePixelData.FromFile(path));
     } catch (FileNotFoundException) {
         // TODO: It would be nice to communicate
         //       information about what went wrong, when
         //       things go wrong.
         return(new FramePixelData(0, 0, new Color[0]));
     }
 }
コード例 #10
0
        private void CompareAndWriteWorker()
        {
            // HACK: This should not be needed!
            Paths.SetStandardWorkingDirectory();

            lock (_resultsSync) {
                while (true)
                {
                    var workItem = _workItems.Take();
                    if (workItem == null)
                    {
                        break;
                    }

                    if (workItem.FrameOutputPath != null)
                    {
                        var directory = Path.GetDirectoryName(workItem.FrameOutputPath);
                        if (!Directory.Exists(directory))
                        {
                            Directory.CreateDirectory(directory);
                        }
                    }

                    float similarity;

                    var framePixelData = new FramePixelData(
                        workItem.TextureWidth, workItem.TextureHeight, workItem.TextureData);
                    var comparePixelData = LoadOrCreateEmptyFramePixelData(workItem.ReferenceImagePath);

                    similarity = CompareFrames(
                        framePixelData,
                        comparePixelData,
                        workItem.FrameComparers);

                    if (workItem.FrameOutputPath != null)
                    {
                        try {
                            framePixelData.Save(workItem.FrameOutputPath);
                        } catch (IOException) {
                            // FIXME: Report this error somehow.
                        }
                    }

                    _results.Add(new FrameComparisonResult(
                                     workItem.FrameInfo.DrawNumber, similarity,
                                     workItem.ReferenceImagePath, workItem.FrameOutputPath));
                }
            }

            lock (_workThreadSync) {
                _workThread = null;
            }
        }
コード例 #11
0
            public FramePixelDataRetriever(FramePixelData source, MINTBinaryStream binaryStream, bool useBulkLoading)
            {
                BaseUrl = source.Parent.BinaryUri;

                StudyInstanceUid  = source.Parent.StudyInstanceUid;
                SeriesInstanceUid = source.Parent.SeriesInstanceUid;
                SopInstanceUid    = source.Parent.SopInstanceUid;
                FrameNumber       = source.FrameNumber;
                TransferSyntaxUid = source.Parent.TransferSyntaxUid;
                BinaryStream      = binaryStream;
                UseBulkLoading    = useBulkLoading;
            }
コード例 #12
0
 public FrameComparisonResult(float similarity, FramePixelData captured, FramePixelData reference,
                              string capturedImagePath, string referenceImagePath, bool failed, bool saveImage, bool saveDiff)
 {
     Similarity         = similarity;
     CapturedData       = captured;
     ReferenceData      = reference;
     CapturedImagePath  = capturedImagePath;
     ReferenceImagePath = referenceImagePath;
     Failed             = failed;
     SaveImage          = saveImage;
     SaveDiff           = saveDiff;
 }
コード例 #13
0
        private static void Normalize(FramePixelData frame)
        {
            var max = new Color(0, 0, 0, 0);

            foreach (var pixel in frame.Data)
            {
                max.B = Math.Max(pixel.B, max.B);
                max.G = Math.Max(pixel.G, max.G);
                max.R = Math.Max(pixel.R, max.R);
                max.A = Math.Max(pixel.A, max.A);
            }

            if (max.B == 0)
            {
                max.B = 255;
            }
            if (max.G == 0)
            {
                max.G = 255;
            }
            if (max.R == 0)
            {
                max.R = 255;
            }
            if (max.A == 0)
            {
                max.A = 255;
            }

            for (var i = 0; i < frame.Data.Length; ++i)
            {
                var pixel = frame.Data[i];


                pixel.B = (byte)(pixel.B * 255 / max.B);
                pixel.G = (byte)(pixel.G * 255 / max.G);
                pixel.R = (byte)(pixel.R * 255 / max.R);
                pixel.A = (byte)(pixel.A * 255 / max.A);

                frame.Data[i] = pixel;
            }
        }
コード例 #14
0
        private static float CompareFrames(
            FramePixelData image, FramePixelData referenceImage,
            Tuple <IFrameComparer, float> [] frameComparers)
        {
            float sumOfWeights = 0;

            foreach (var item in frameComparers)
            {
                sumOfWeights += item.Item2;
            }

            float similarity = 0;

            foreach (var item in frameComparers)
            {
                var comparer = item.Item1;
                var weight   = item.Item2;
                similarity += comparer.Compare(image, referenceImage) * weight / sumOfWeights;
            }
            return(similarity);
        }
コード例 #15
0
        public float Compare(FramePixelData a, FramePixelData b)
        {
            int minWidth, maxWidth, minHeight, maxHeight;

            MathUtility.MinMax(a.Width, b.Width, out minWidth, out maxWidth);
            MathUtility.MinMax(a.Height, b.Height, out minHeight, out maxHeight);

            var rect = new System.Drawing.Rectangle(0, 0, minWidth, minHeight);

            long error = 0;

            int index = 0;

            for (int y = 0; y < rect.Height; ++y)
            {
                for (int x = 0; x < rect.Width; ++x)
                {
                    error += Delta(a.Data [index], b.Data [index]);
                    index++;
                }
            }

            // FIXME: To temporarily accommodate the differing
            //        resolutions of mobile platforms, we just
            //        ignore all non-overlapping pixels.  This
            //        is not ideal, but it's good enough for now.
            // Mark all out-of-bounds pixels as non-match.
            //error += PixelArgb.MaxDelta * ((maxWidth * maxHeight) - (minWidth * minHeight));

            var dissimilarity = ((float)error / (float)(PixelArgb.MaxDelta * minWidth * minHeight));

            // Project dissimilarity to a logarithmic scale.  The
            // difference between having zero pixels wrong and one
            // pixel wrong is more significant than the difference
            // betweeen 10,000 wrong and 10,001.
            return(1.0f - (float)Math.Pow(dissimilarity, 0.5));
        }
コード例 #16
0
            public FramePixelDataRetriever(FramePixelData source)
            {
                string host       = source.Parent._host;
                string wadoPrefix = source.Parent._wadoUriPrefix;
                int    wadoPort   = source.Parent._wadoServicePort;

                try
                {
                    BaseUrl = new Uri(String.Format(wadoPrefix, host, wadoPort));
                }
                catch (FormatException ex)
                {
                    // this exception happens if the FormatWadoUriPrefix setting is invalid.
                    throw new Exception(SR.MessageStreamingClientConfigurationException, ex);
                }

                AETitle = source.Parent._aeTitle;

                StudyInstanceUid  = source.Parent.StudyInstanceUid;
                SeriesInstanceUid = source.Parent.SeriesInstanceUid;
                SopInstanceUid    = source.Parent.SopInstanceUid;
                FrameNumber       = source.FrameNumber;
                TransferSyntaxUid = source.Parent.TransferSyntaxUid;
            }
コード例 #17
0
        private static FramePixelData CreateDiff(FramePixelData a, FramePixelData b)
        {
            int minWidth, maxWidth, minHeight, maxHeight;

            MathUtility.MinMax(a.Width, b.Width, out minWidth, out maxWidth);
            MathUtility.MinMax(a.Height, b.Height, out minHeight, out maxHeight);

            var diff = new FramePixelData(maxWidth, maxHeight);

            for (var y = 0; y < minHeight; ++y)
            {
                var indexA    = y * a.Width;
                var indexB    = y * b.Width;
                var indexDiff = y * diff.Width;

                for (var x = 0; x < minWidth; ++x)
                {
                    // Ignore alpha.  If alpha diffs are
                    // needed, a special strategy will have
                    // to be devised, since XOR'ing two
                    // opaque pixels will cause a totally
                    // transparent pixel and hide any other
                    // difference.
                    diff.Data [indexDiff] = new Color(
                        (byte)(a.Data [indexA].R ^ b.Data [indexB].R),
                        (byte)(a.Data [indexA].G ^ b.Data [indexB].G),
                        (byte)(a.Data [indexA].B ^ b.Data [indexB].B));

                    indexA++;
                    indexB++;
                    indexDiff++;
                }
            }

            return(diff);
        }
コード例 #18
0
 public StreamingSopFrameData(int frameNumber, StreamingSopDataSource parent)
     : base(frameNumber, parent, LargeObjectContainerData.PresetNetworkLoadedData)
 {
     _framePixelData = new FramePixelData(this.Parent, frameNumber);
     _overlayData    = new byte[16][];
 }
コード例 #19
0
		private static void Normalize (FramePixelData frame)
		{
			Color max = new Color(0, 0, 0, 0);
			foreach (var pixel in frame.Data) {
				max.B = Math.Max (pixel.B, max.B);
				max.G = Math.Max (pixel.G, max.G);
				max.R = Math.Max (pixel.R, max.R);
				max.A = Math.Max (pixel.A, max.A);
			}

			if (max.B == 0) max.B = 255;
			if (max.G == 0) max.G = 255;
			if (max.R == 0) max.R = 255;
			if (max.A == 0) max.A = 255;

			for (int i = 0; i < frame.Data.Length; ++i) {
				Color pixel = frame.Data[i];


				pixel.B = (byte)(pixel.B * 255 / max.B);
				pixel.G = (byte)(pixel.G * 255 / max.G);
				pixel.R = (byte)(pixel.R * 255 / max.R);
				pixel.A = (byte)(pixel.A * 255 / max.A);

				frame.Data[i] = pixel;
			}
		}
コード例 #20
0
		private static FramePixelData CreateDiff (FramePixelData a, FramePixelData b)
		{
			int minWidth, maxWidth, minHeight, maxHeight;

			MathUtility.MinMax (a.Width, b.Width, out minWidth, out maxWidth);
			MathUtility.MinMax (a.Height, b.Height, out minHeight, out maxHeight);

			var diff = new FramePixelData (maxWidth, maxHeight);

			for (int y = 0; y < minHeight; ++y) {

				int indexA = y * a.Width;
				int indexB = y * b.Width;
				int indexDiff = y * diff.Width;

				for (int x = 0; x < minWidth; ++x) {
					// Ignore alpha.  If alpha diffs are
					// needed, a special strategy will have
					// to be devised, since XOR'ing two
					// opaque pixels will cause a totally
					// transparent pixel and hide any other
					// difference.
					diff.Data [indexDiff] = new Color (
						(byte) (a.Data [indexA].R ^ b.Data [indexB].R),
						(byte) (a.Data [indexA].G ^ b.Data [indexB].G),
						(byte) (a.Data [indexA].B ^ b.Data [indexB].B));

					indexA++;
					indexB++;
					indexDiff++;
				}
			}

			return diff;
		}
コード例 #21
0
 public float Compare(FramePixelData a, FramePixelData b)
 {
     return(_value);
 }
コード例 #22
0
        protected void CheckFrames()
        {
            if (!_framePrepared)
            {
                throw new Exception("PrepareFrameCapture must be called before rendering to be able to check frames.");
            }

            // submit the current frame if one is prepared, but none are submitted yet
            if (!_frameSubmitted)
            {
                SubmitFrame();
            }

            var folderName = TestContext.CurrentContext.GetTestFolderName();
            var referenceImageDirectory = Paths.ReferenceImage(folderName);
            var outputDirectory         = Paths.CapturedFrame(folderName);
            var fileName           = TestContext.CurrentContext.GetTestFrameFileNameFormat(_totalFramesExpected);
            var capturedImagePath  = Path.Combine(outputDirectory, fileName);
            var referenceImagePath = Path.Combine(referenceImageDirectory, fileName);

            var allResults    = new List <FrameComparisonResult>();
            var failedResults = new List <FrameComparisonResult>();
            var noReference   = new List <string>();

            for (var i = 0; i < _submittedFrames.Count; i++)
            {
                var frame = _submittedFrames[i];

                var capturedPath  = string.Format(capturedImagePath, i + 1);
                var referencePath = string.Format(referenceImagePath, i + 1);

                if (!File.Exists(referencePath))
                {
                    // no reference frame is available, so just write the image and track the failure
                    if (WriteCapture == WriteSettings.Always || WriteCapture == WriteSettings.WhenFailed)
                    {
                        Directory.CreateDirectory(outputDirectory);
                        _writerThread.AddAction(() =>
                                                frame.Save(capturedPath));
                    }
                    noReference.Add(referencePath);
                    continue;
                }

                var refFrame        = FramePixelData.FromFile(referencePath);
                var frameSimilarity = _frameComparer.Compare(frame, refFrame);

                var failed = frameSimilarity < Similarity;

                var writeCapture = WriteCapture == WriteSettings.Always ||
                                   (WriteCapture == WriteSettings.WhenFailed && failed);
                var writeDiff = WriteDiffs == WriteSettings.Always ||
                                (WriteDiffs == WriteSettings.WhenFailed && failed);

                var result = new FrameComparisonResult(frameSimilarity, frame, refFrame,
                                                       capturedPath, referencePath, failed, writeCapture, writeDiff);

                allResults.Add(result);
                if (failed)
                {
                    failedResults.Add(result);
                }

                if (result.SaveImage)
                {
                    Directory.CreateDirectory(outputDirectory);
                    _writerThread.AddAction(() =>
                                            result.CapturedData.Save(result.CapturedImagePath));
                }

                if (result.SaveDiff)
                {
                    var name = string.Format(fileName, i + 1);
                    var path = GetDiffPath(name);
                    result.DiffPath = path;
                    Directory.CreateDirectory(Path.GetDirectoryName(path));
                    _writerThread.AddAction(() =>
                                            WriteDiff(result.CapturedData, result.ReferenceData, path));
                }
            }

            _framesChecked = true;

            // write results to console
            WriteComparisonResultReport(allResults, noReference);

            // wait for the writing thread so it doesn't get terminated early
            if (!_writerThread.Finished)
            {
                _writerThread.Thread.Join();
            }

            // now do the actual assertions
            if (ExactNumberSubmits && _totalFramesExpected != allResults.Count)
            {
                Assert.Fail(
                    "Expected {0} frame comparison result(s), but found {1}",
                    _totalFramesExpected, allResults.Count);
            }

            if (failedResults.Count > 0)
            {
                Assert.Fail(
                    "{0} of {1} frames failed the similarity test.",
                    failedResults.Count, allResults.Count);
            }

            if (noReference.Count > 0)
            {
                Assert.Fail(
                    "Did not find reference image(s): " + noReference.Aggregate((s1, s2) => s1 + ", " + s2));
            }
        }
コード例 #23
0
 public StreamingSopFrameData(int frameNumber, StreamingSopDataSource parent)
     : base(frameNumber, parent, RegenerationCost.High)
 {
     _framePixelData = new FramePixelData(this.Parent, frameNumber);
     _overlayData    = new byte[16][];
 }