Когда я передаю изображение в мою обученную модель, оно дает + 80% точности для объектов, которые не обучены в модели. - PullRequest
1 голос
/ 02 апреля 2019

Я работаю над Unity-Android приложением, которое распознает жесты рук.Изображения, которые я использовал для обучения модели: 50x50 Черно-белые изображения с ручной сегментацией по значениям HSV .Теперь то же самое делается при тестировании модели, но проблема в том, что: когда в камере нет руки, она все равно что-то обнаруживает (что-либо - через мобильную камеру), потому что HSV не является точным, и когда это изображение с (без руки) подается на модель , она по-прежнему дает 80% + точность и определяет случайный класс для нее.

Изображения и код, с помощью которых обучается модельсвязан.

Я использую TensorflowSharp для загрузки моей модели.Для openCV я использую OpenCV для Unity У меня есть 4 жеста (4 класса), где каждый класс имеет 4-4,5 тыс. Изображений, всего 17 тыс. Изображений.Примеры изображений

Класс 1

Class 1

Класс 2

Class 2

Класс 3

Class 3

Класс 4

Class 4

Если вам нужна какая-либо другая информация, пожалуйста, сообщите мне, любая помощь будет оценена.

  • Я пробовал модели обнаружения рук, чтобы они могли определять, когда нет руки, но они не точны.
  • Я попробовал ввод от пользователя, чтобы коснуться его руки, он работает нормальноно когда рука убирается, она снова начинает обнаруживать случайным образом из-за ВПГ.
  • Я пробовал сопоставлять функции через SIFT и т. д., но они очень дороги.
  • Я пробовал сопоставлять шаблоны, которые из моегоперспектива должна работать, но дает странные результаты.

using (var graph = new TFGraph())
{
graph.Import(buffer);
using (var session = new TFSession(graph))
{
    Stopwatch sw = new Stopwatch();
    sw.Start();
    var runner = session.GetRunner();
    Mat gray = new Mat();
    Mat HSVMat = new Mat();
    Imgproc.resize(touchedRegionRgba, gray, new
    OpenCVForUnity.Size(50, 50));
    Imgproc.cvtColor(gray, HSVMat, Imgproc.COLOR_RGB2HSV_FULL);
    Imgproc.cvtColor(gray, gray, Imgproc.COLOR_RGBA2GRAY);
    for (int i = 0; i < gray.rows(); i++)
    {
        int count = 0;
        for (int j = 200; count<gray.cols(); j++)
        {
            double[] Hvalue = HSVMat.get(i, count);
            if (!((detector.mLowerBound.val[0] <= Hvalue[0] && Hvalue[0] <= detector.mUpperBound.val[0]) &&
                (detector.mLowerBound.val[1] <= Hvalue[1] && Hvalue[1] <= detector.mUpperBound.val[1]) &&
                (detector.mLowerBound.val[2] <= Hvalue[2] && Hvalue[2] <= detector.mUpperBound.val[2])))
            {
                gray.put(i, count, new byte[] { 0 });
            }
        }
    }
    var tensor = Util.ImageToTensorGrayScale(gray);
    //runner.AddInput(graph["conv1_input"][0], tensor);
    runner.AddInput(graph["zeropadding1_1_input"][0], tensor);
    //runner.Fetch(graph["outputlayer/Softmax"][0]);
    //runner.Fetch(graph["outputlayer/Sigmoid"][0]);
    runner.Fetch(graph["outputlayer/Softmax"][0]);
    var output = runner.Run();
    var vecResults = output[0].GetValue();
    float[,] results = (float[,])vecResults;
    sw.Stop();
    int result = Util.Quantized(results);
    //numberOfFingersText.text += $"Length={results.Length} Elapsed= {sw.ElapsedMilliseconds} ms, Result={result}, Acc={results[0, result]}";
    }
}


# EDITED MODEL, MODEL 1

model = models.Sequential()
model.add(layers.ZeroPadding2D((2, 2), batch_input_shape=(None, 50, 50, 1), name="zeropadding1_1"))   

#54x54 fed in due to zero padding
model.add(layers.Conv2D(8, (5, 5), activation='relu', name='conv1_1'))
model.add(layers.ZeroPadding2D((2, 2), name="zeropadding1_2"))
model.add(layers.Conv2D(8, (5, 5), activation='relu', name='conv1_2'))

model.add(layers.MaxPooling2D((2, 2), strides=(2, 2), name="maxpool_1")) #convert 50x50 to 25x25

#25x25 fed in
model.add(layers.ZeroPadding2D((2, 2), name="zeropadding2_1"))
model.add(layers.Conv2D(16, (5, 5), activation='relu', name='conv2_1'))
model.add(layers.ZeroPadding2D((2, 2), name="zeropadding2_2"))
model.add(layers.Conv2D(16, (5, 5), activation='relu', name='conv2_2'))

model.add(layers.MaxPooling2D((5, 5), strides=(5, 5), name="maxpool_2")) #convert 25x25 to 5x5

#5x5 fed in
model.add(layers.ZeroPadding2D((2, 2), name="zeropadding3_1"))
model.add(layers.Conv2D(40, (5, 5), activation='relu', name='conv3_1'))
model.add(layers.ZeroPadding2D((2, 2), name="zeropadding3_2"))
model.add(layers.Conv2D(32, (5, 5), activation='relu', name='conv3_2'))

model.add(layers.Dropout(0.2))
model.add(layers.Flatten())

model.add(layers.Dense(512, activation='relu'))
model.add(layers.Dropout(0.2))
model.add(layers.Dense(512, activation='relu'))
model.add(layers.Dropout(0.15))
model.add(layers.Dense(512, activation='relu'))
model.add(layers.Dropout(0.1))
model.add(layers.Dense(512, activation='relu'))
model.add(layers.Dense(512, activation='relu'))
model.add(layers.Dense(512, activation='relu'))
model.add(layers.Dense(512, activation='relu'))
model.add(layers.Dense(512, activation='relu'))

model.add(layers.Dense(4, activation='softmax', name="outputlayer"))

# MODEL 2, used a few more that I haven't mentioned

model = models.Sequential()
model.add(layers.ZeroPadding2D((2, 2), batch_input_shape=(None, 50, 50, 1), name="zeropadding1_1"))   

#54x54 fed in due to zero padding
model.add(layers.Conv2D(8, (5, 5), activation='relu', name='conv1_1'))
model.add(layers.ZeroPadding2D((2, 2), name="zeropadding1_2"))
model.add(layers.Conv2D(8, (5, 5), activation='relu', name='conv1_2'))

model.add(layers.MaxPooling2D((2, 2), strides=(2, 2), name="maxpool_1")) #convert 50x50 to 25x25

#25x25 fed in
model.add(layers.ZeroPadding2D((2, 2), name="zeropadding2_1"))
model.add(layers.Conv2D(16, (5, 5), activation='relu', name='conv2_1'))
model.add(layers.ZeroPadding2D((2, 2), name="zeropadding2_2"))
model.add(layers.Conv2D(16, (5, 5), activation='relu', name='conv2_2'))

model.add(layers.MaxPooling2D((5, 5), strides=(5, 5), name="maxpool_2")) #convert 25x25 to 5x5

#5x5 fed in
model.add(layers.ZeroPadding2D((2, 2), name="zeropadding3_1"))
model.add(layers.Conv2D(40, (5, 5), activation='relu', name='conv3_1'))
model.add(layers.ZeroPadding2D((2, 2), name="zeropadding3_2"))
model.add(layers.Conv2D(32, (5, 5), activation='relu', name='conv3_2'))

model.add(layers.Dropout(0.2))
model.add(layers.Flatten())

model.add(layers.Dense(512, activation='tanh'))
model.add(layers.Dropout(0.2))
model.add(layers.Dense(512, activation='tanh'))
model.add(layers.Dropout(0.15))
model.add(layers.Dense(512, activation='tanh'))
model.add(layers.Dropout(0.1))
model.add(layers.Dense(512, activation='tanh'))
model.add(layers.Dense(512, activation='tanh'))
model.add(layers.Dense(512, activation='tanh'))
model.add(layers.Dense(512, activation='tanh'))
model.add(layers.Dense(512, activation='tanh'))

model.add(layers.Dense(4, activation='sigmoid', name="outputlayer"))

Ожидаемые результаты: более высокая точность на фактических 4 классах обученной модели и ниже на остальных.

Фактические результаты: более высокая точность на фактических 4 классах, а также на остальной части изображенияему это надоело.

1 Ответ

1 голос
/ 02 апреля 2019

По моему мнению, основная проблема в том, что вы не можете определить, присутствует ли рука на изображении .Вам необходимо локализовать руку.

  1. Сначала нам нужно определить, присутствует ли рука или нет.Вы можете попробовать сиамские сети для этих задач.Я успешно использовал их для выявления аномалий кожи.Вы можете сослаться на это -> «Обучение одним выстрелом с использованием сиамских сетей с использованием Keras» Харшалла Ламбы https://link.medium.com/xrCQOD8ntV и «Сходство лиц с сиамскими сетями в PyTorch» Харшвардхана Гупты https://link.medium.com/htBzNmUCyV

  2. Сеть выдаст двоичный вывод.Если рука присутствует, то будут видны значения, близкие к единице.В противном случае будут видны значения, близкие к нулю.

Другие, модели ML, такие как YOLO, используются для локализации объектов, но сиамские сети просты и трезвы.

Сиамские сети на самом деле используют один и тот же CNN и, следовательно, они сиамские или соединенные.Они измеряют абсолютную погрешность между вложениями изображений и пытаются аппроксимировать функцию сходства между изображениями.

После правильного обнаружения можно выполнить классификацию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...