Сравнение снимков экрана с OpenCV и C# .NETC#

Место общения программистов C#
Ответить
Anonymous
 Сравнение снимков экрана с OpenCV и C# .NET

Сообщение Anonymous »

Я работаю над решением, которое позволит улучшить сравнение скриншотов наших компаний. В настоящее время мы наблюдаем множество сбоев из-за различий в пикселях и т. д. Я реализовал решение в OpenCvSharp, которое работает на 90%. Однако некоторые изображения, похоже, дают ложные срабатывания, рисуя контуры (красные рамки) вокруг вещей, которые не изменились. Кажется, это несколько случайно и не связано с каким-либо конкретным типом изображения. Подробности смотрите на изображениях ниже (не обращайте внимания на поля в верхнем левом и правом углах, я сделал это, чтобы скрыть информацию о конкретной компании)
Базовый файл:
Изображение

Файл различий (после сравнения выполнено) см. маленькую красную рамку вокруг данных графика:
Изображение

Эта работа направлена ​​на то, чтобы избежать проблем, подобных описанным ниже, но после почти двух недель разработки и настройки кода у меня начинают заканчиваться идеи. Код, который я сейчас использую, приведен ниже:

Код: Выделить всё

  public static void CompareImagesForDifferences(string baselineImagePath, Screenshot currentImageScreenshot, string testName, ImageComparisonConfig imageConfig)
{
string currentImagePath = SaveCurrentImage(currentImageScreenshot, testName, imageConfig);

Mat baselineImage = LoadImage(baselineImagePath);
Mat currentImage = LoadImage(currentImagePath);

ResizeImage(baselineImage, currentImage);

Mat baselineGray = ConvertToGrayscale(baselineImage);
Mat currentGray = ConvertToGrayscale(currentImage);

double ssimScore = ComputeSSIM(baselineGray, currentGray, out Mat ssimMap);

if (ssimScore >= double.Parse(imageConfig.GetSSIMThresholdSetting()))
{
// Images are identical
Logger.Info("Images are similar. No significant differences detected.");
return;
}

if (isSignificantChangesBetweenImages(baselineImage, currentImage, ssimMap, imageConfig, out Mat filledImage))
{
string diffImagePath = $@"{imageConfig.GetFailuresPath()}\\{testName}_Diff.png";
SaveDiffImage(filledImage, testName, imageConfig, diffImagePath, baselineImagePath);
}
}
Каждый из соответствующих методов приведен ниже (без учета SaveCurrentImage):

Код: Выделить всё

private static Mat LoadImage(string path)
{
if (!File.Exists(path))
{
throw new FileNotFoundException($"The specified image file was not found at path: {path} - Please ensure the baseline is created.");
}

Mat image = Cv2.ImRead(path, ImreadModes.Color);

// Check if the matrix is empty (indicating a load failure)
if (image.Empty())
{
throw new ImageComparisonException($"Failed to load a valid image from path: {path}.  The image might be corrupted or unsupported.");
}

return image;
}

private static Mat ConvertToGrayscale(Mat image)
{
Mat gray = new Mat();
Cv2.CvtColor(image, gray, ColorConversionCodes.BGR2GRAY);
Cv2.GaussianBlur(gray, gray, new Size(5, 5), 0);
return gray;
}
Я считаю, что проблема кроется где-то в приведенном ниже коде:

Код: Выделить всё

private static bool isSignificantChangesBetweenImages(Mat baselineImage, Mat currentImage, Mat ssimMap, ImageComparisonConfig imageConfig, out Mat filledImage)
{
filledImage = currentImage.Clone();
Mat diff = new Mat();
ssimMap.ConvertTo(diff, MatType.CV_8UC1, 255);

Mat thresh = new Mat();
Cv2.Threshold(diff, thresh, 0, 255, ThresholdTypes.BinaryInv | ThresholdTypes.Otsu);

Point[][] contourDifferencePoints;
HierarchyIndex[] hierarchyIndex;
Cv2.FindContours(thresh, out contourDifferencePoints, out hierarchyIndex, RetrievalModes.List, ContourApproximationModes.ApproxSimple);

return DrawSignificantChanges(baselineImage, contourDifferencePoints, imageConfig, filledImage);
}

private static bool DrawSignificantChanges(Mat baselineImage, Point[][] contours, ImageComparisonConfig imageConfig, Mat filledImage, double minAreaRatio = 0.0001, double maxAreaRatio = 0.1)
{
bool hasSignificantChanges = false;
double totalImageArea = baselineImage.Width * baselineImage.Height;
double minArea = totalImageArea * minAreaRatio;
double maxArea = totalImageArea * maxAreaRatio;

foreach (var contour in contours)
{
double area = Cv2.ContourArea(contour);
if (area < minArea || area > maxArea) continue;

Rect boundingRect = Cv2.BoundingRect(contour);

// Ignore changes near the image border
int borderThreshold = 5;
if (boundingRect.X = baselineImage.Height - borderThreshold)
{
continue;
}

// Check if the difference is significant enough
using (Mat roi = new Mat(baselineImage, boundingRect))
{
Scalar mean = Cv2.Mean(roi);
if (mean.Val0 < int.Parse(imageConfig.GetPixelToleranceSetting())) // Adjust this threshold as needed
{
continue;
}
}

// Draw Rectangle shape in red around the differences
Cv2.Rectangle(filledImage, boundingRect, new Scalar(0, 0, 255), 2);
hasSignificantChanges = true;
}
return hasSignificantChanges;
}
Я попытался настроить значения порога, но снова получил аналогичные результаты. Есть ли кто-нибудь, у кого есть что-то подобное? Как вы можете видеть на изображениях ниже, существенных отличий от человеческого глаза нет. Одна из проблем, с которой я сталкиваюсь, заключается в том, что код сравнения должен улавливать небольшие изменения, такие как процентные изменения графика.

Подробнее здесь: https://stackoverflow.com/questions/791 ... -sharp-net
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»