Обнаружения от CaffeModel находятся за пределами изображения - PullRequest
0 голосов
/ 14 июня 2019

Я пытаюсь создать программу, которая распознает и анонимизирует лица на таких вещах, как удостоверения личности. Я перевел пример Python, который нашел , на C #, и он работал безупречно на большинстве примеров. Тем не менее, некоторые изображения дают обнаружения, которые находятся за пределами.

Шаги для воспроизведения:

  1. Создание нового консольного проекта.
  2. Добавьте пакет nuget: ' OpenCvSharp4.Windows '.
  3. Загрузите необходимые файлы (внизу этого вопроса).
  4. Вставьте код и поместите файлы в папку с именами файлов в папке отладки программы.

Код для воспроизведения:

static void Main( string[] args )
{
    anonymize( new byte[][] { File.ReadAllBytes("files\\elon-musk.jpg") }, "files\\deploy.prototxt", "files\\model.caffemodel" );
    Console.ReadKey();
}

private static void anonymize( byte[][] files, string caffeProtoTxtFile, string caffeModelFile )
{
    int i = 0;
    foreach( var fileBytes in files )
    {
        i++;
        Console.WriteLine( $"Image nr.{i}" );
        using( var net = OpenCvSharp.Dnn.Net.ReadNetFromCaffe( caffeProtoTxtFile, caffeModelFile ) )
        {
            var image = Cv2.ImDecode( fileBytes, ImreadModes.AnyColor | ImreadModes.AnyDepth );

            Console.WriteLine( $"\nImage size:\nWidth:{image.Width}\nHeight:{image.Height}\n\n" );

            var detections = detectFaceDNN( image, net, true );
            image.Dispose();
        }
    }
}

private static Rect[] detectFaceDNN( Mat image, OpenCvSharp.Dnn.Net net, bool draw )
{
    var detectionRectangles = new List<Rect>();

    using( var blob = OpenCvSharp.Dnn.CvDnn.BlobFromImage( image, 1, size: new Size( image.Width, image.Height ), mean: new Scalar( 91.4953, 103.8827, 131.0912 ) ) )
    {
        net.SetInput( blob );
        using( var detections = net.Forward() )
        {
            for( int i = 0; i < detections.Size( 2 ); i++ )
            {
                var confidence = detections.At<float>( 0, 0, i, 2 );

                if( confidence > 0.85 )
                {
                    var startX = (int)Math.Round( detections.At<float>( 0, 0, i, 3 ) * image.Width );
                    var startY = (int)Math.Round( detections.At<float>( 0, 0, i, 4 ) * image.Height );
                    var endX = (int)Math.Round( detections.At<float>( 0, 0, i, 5 ) * image.Width );
                    var endY = (int)Math.Round( detections.At<float>( 0, 0, i, 6 ) * image.Height );

                    var coordinatesOutOfBounds = endX > image.Width || endY > image.Height || startX < 0 || startY < 0;

                    //Don't draw if its out of bounds
                    if( coordinatesOutOfBounds )
                    {
                        Console.WriteLine( $"Coordinates:\nX: {startX} - {endX}\nY: {startY.ToString().PadLeft(4)} - {endY.ToString().PadLeft(4)}\n" );
                        continue;
                    }

                    if( draw )
                        Cv2.Rectangle( image, pt1: new Point( startX, startY ), pt2: new Point( endX, endY ), color: new Scalar(), thickness: -1 );

                    detectionRectangles.Add( new Rect( startX, startY, endX - startX, endY - startY ) );
                }
            }
        }
    }
    return detectionRectangles.ToArray();
}

Этот код выведет любые координаты, выходящие за пределы.

Файлы:
CaffeModel
Prototxt
Изображение

Поскольку я не могу использовать изображения, используемые в производстве (конфиденциальная информация), я нашел другое изображение, которое также имеет эти координаты.

По сути, мой вопрос заключается в том, почему я получаю эти «недействительные» координаты из обнаружений, но другие действительные координаты находятся в правильном месте и во всем. Я чувствую, что делаю что-то не так и не должен получать эти обнаружения в противном случае.

1 Ответ

0 голосов
/ 14 июня 2019

Да, это происходит когда-то, но не всегда (в моем случае), вы должны выполнить следующую проверку, прежде чем переходить к другим вещам:

if (startX < 0) {
    startX = 0;
}
if (startY < 0) {
    startY  = 0;
}
if (startX + (endX - startX ) > frame.cols) {
    endX = frame.cols;
}
if (startY + (endY - startY ) > frame.rows) {
    endY = frame.rows;
}

Так что это будет входящий сейчас.

Надеюсь, это поможет!

...