Перейти к содержимому
Compvision.ru

iskees

Пользователи
  • Количество публикаций

    202
  • Зарегистрирован

  • Посещение

  • Days Won

    19

Сообщения, опубликованные пользователем iskees


  1. Есть проста сверточная сеть (keras+tf),  размер входного слоя не фиксированный. При прогоне на CPU все нормально, чем больше входной изображение тем дольше обработка. Но при выборе Backend cuda получается такая картина:

    • если прогонять данные одного размера (например 240х180), то все хорошо
    • если размер входных данных постоянно меняется (сперва 240х180, потом  240х179 и так по кругу) то производительность падает в 10 раз. 

    opencv 4.2.0-dev

    jetson nano


  2. 21 час назад, Nuzhny сказал:

    В OpenCV уже давно есть модуль для нейросетей opencv_dnn, есть специализированный для детекции на dnn, а сейчас есть и dnn на CUDA. Так что он актуальности своей терять не собирается, не хороните

    в 4.2 добавили? На jetson работает?


  3. Я бы больше внимания уделил именно освещению, что бы отделить стекло от фона. Как вариант можно поставить сверху/снизу длинный узкий прожектор которые светит строго вертикально и цвет его должен быть отличным от фона (зеленый). Заносите стекло вертикально под прожектор и горизонтальные грани стекла должны засветится цветом прожектора. В итоге имеем границы стекла + так как прожектор узкий имеем и примерную область в которой стекло расположено, что поможет в расчете размеров.

    • Like 1

  4. использую такой скрипт для иvпорта в opencv, сверточные слои работают

     

    #region Imports
    from tensorflow.python.tools import freeze_graph
    import tensorflow as tf
    import numpy as np
    from keras.models import Model # basic class for specifying and training a neural network
    from keras.layers import Input, Dense # the two types of neural network layer we will be using
    from keras.utils import np_utils # utilities for one-hot encoding of ground truth values
    from keras.models import Sequential
    from keras.layers import Input, Convolution2D, MaxPooling2D, Dense, Dropout, Flatten, Reshape, Activation
    from keras.engine.topology  import InputLayer
    from keras.layers.core import Dense as DenseLayer
    from keras import backend as K
    import os
    from tensorflow.core import framework
    #endregion
    
    
    
    
    def find_all_nodes(graph_def, **kwargs):
        for node in graph_def.node:
            for key, value in kwargs.items():
                if getattr(node, key) != value:
                    break
            else:
                yield node
        raise StopIteration
    
    
    def find_node(graph_def, **kwargs):
        try:
            return next(find_all_nodes(graph_def, **kwargs))
        except StopIteration:
            raise ValueError(
                'no node with attributes: {}'.format(
                    ', '.join("'{}': {}".format(k, v) for k, v in kwargs.items())))
    
    
    def walk_node_ancestors(graph_def, node_def, exclude=set()):
        openlist = list(node_def.input)
        closelist = set()
        while openlist:
            name = openlist.pop()
            if name not in exclude:
                node = find_node(graph_def, name=name)
                openlist += list(node.input)
                closelist.add(name)
        return closelist
    
    
    def remove_nodes_by_name(graph_def, node_names):
        for i in reversed(range(len(graph_def.node))):
            if graph_def.node[i].name in node_names:
                del graph_def.node[i]
    
    
    def make_shape_node_const(node_def, tensor_values):
        node_def.op = 'Const'
        node_def.ClearField('input')
        node_def.attr.clear()
        node_def.attr['dtype'].type = framework.types_pb2.DT_INT32
        tensor = node_def.attr['value'].tensor
        tensor.dtype = framework.types_pb2.DT_INT32
        tensor.tensor_shape.dim.add()
        tensor.tensor_shape.dim[0].size = len(tensor_values)
        for value in tensor_values:
            tensor.tensor_content += value.to_bytes(4, 'little')
        output_shape = node_def.attr['_output_shapes']
        output_shape.list.shape.add()
        output_shape.list.shape[0].dim.add()
        output_shape.list.shape[0].dim[0].size = len(tensor_values)
    
    
    def make_cv2_compatible(graph_def):
        # A reshape node needs a shape node as its second input to know how it
        # should reshape its input tensor.
        # When exporting a model using Keras, this shape node is computed
        # dynamically using `Shape`, `StridedSlice` and `Pack` operators.
        # Unfortunately those operators are not supported yet by the OpenCV API.
        # The goal here is to remove all those unsupported nodes and hard-code the
        # shape layer as a const tensor instead.
        for reshape_node in find_all_nodes(graph_def, op='Reshape'):
    
            # Get a reference to the shape node
            shape_node = find_node(graph_def, name=reshape_node.input[1])
    
            # Find and remove all unsupported nodes
            garbage_nodes = walk_node_ancestors(graph_def, shape_node,
                                                exclude=[reshape_node.input[0]])
            remove_nodes_by_name(graph_def, garbage_nodes)
    
            # Infer the shape tensor from the reshape output tensor shape
            if not '_output_shapes' in reshape_node.attr:
                raise AttributeError(
                    'cannot infer the shape node value from the reshape node. '
                    'Please set the `add_shapes` argument to `True` when calling '
                    'the `Session.graph.as_graph_def` method.')
            output_shape = reshape_node.attr['_output_shapes'].list.shape[0]
            output_shape = [dim.size for dim in output_shape.dim]
    
            # Hard-code the inferred shape in the shape node
            make_shape_node_const(shape_node, output_shape[1:])
    
    def Save2(model_name,model):
        sess = K.get_session()
        graph_def = sess.graph.as_graph_def(add_shapes=True)
        graph_def = tf.graph_util.convert_variables_to_constants(sess, graph_def, [model.output.name.split(':')[0]])
        make_cv2_compatible(graph_def)
    
        # Print the graph nodes
        print('\n'.join(node.name for node in graph_def.node))
    
        # Save the graph as a binary protobuf2 file
        tf.train.write_graph(graph_def, '', model_name+'.pb', as_text=False)
    
     
    

    само сохранение такое (model  это keras, backend tf):

    import TFfreez
    TFfreez.Save2("d://number.pb",model )

     


  5. 1. SVM+HOG на GPU для риалтайм подходит

    2. "И решение я вижучтоб получше разобраться с SVM, с тем что делается с HOG чтобы стать датасетом для SVM". Ничего с ним не делается, для каждого образца считается дескриптор, добавляется метка и все.


  6. Все три примера довольно тривиальны, по времени обработки на нормальном железе (в смысле не четвертый пентиум, а что то помоложе) и с таким размером файла 5мс максимум.  Это средствами opencv.

    Но я бы сперва попробовал tesseract.


  7. Если зимний объект отличается от летнего, то нужно что-бы в выборке были оба варианта. Но знаки не отличаются от времени года, а вот от времени суток очень даже за счет отражающих полос. 

    HOG-SVM намного менее чувствителен к яркости (основан на  ее градиенте), менее чувствителен к искажениям и шуму. В целом между этими двумя методами пропасть в плоскости качества.

    • Like 1

  8. Не смотрел как там в dlib устроено обучение этого классификатора, но судя по коду на вход подается набор изображений с указанием расположения целевых объектов.   

    Положительные образцы для обучения это целевые объекты, отрицательные все остальные части изображения. 

    Что бы это работало нужно:

    1. Что бы изображения были достаточно большие и целевой объект не занимал все изображение, а малую часть
    2. Образцов должно быть много, от 1000

    Датасет можно отправить так же архивом но с файлом положения объектов. 

     

    А вообще проект так себе. Проще взять да с 0 написать на том же питоне, ничего сложно там нет.


  9. СДК по распознаванию номеров сейчас много. Качество распознавания у них примерно одинаковое и развитие идет больше в сторону улучшения производительности. Года 3-4 назад камеры были 0.5Мп и 25фпс, сейчас уже fhd 40фпс при железе в лучше случае средненький i5.

    Но использует такие системы в основном ГАИ. И кроме самого распознавания номера им нужно еще и выявлять нарушения (замер скорости по кадру, проезд на красный и т.д.) которые еще и постоянно добавляются. На мой взгляд более остро сейчас стоит вопрос именно  с последующей обработкой уже распознанных номеров, построение траекторий, привязка к местности и т.д.


  10. Устанавливал таким образом:

    1. Visual studio 2017 с выбранными при установке python и anaconda 
    2. Через conda установил tensorflow, tensorflow-gpu, keras

    Обучается без особых проблем на gpu, больше проблем было с импортом результатов в opencv (нет слоя flatten, chanal_first вместо chanal_last). Сверточные слои  заработали только на Opencv 3.4.1, на 3.3.1 ошибок нет но результат всегда один (активирован последний нейрон выходного слоя), на 3.4.3 ошибка при вызове forward. Opencv в c# через обертку opencvsharp.


  11. Чистый "анализ изображения" тут мало пригоден, у целевого объекта нет особых отличительных признаков.

    Я вижу тут два варианта:

    1. "Классический" поиск объекта (hog, haar и т.п.) 
    2. Глубокий сетки

    Работать должно и днем и ночью, ничего критичного тут нет.

    Но вообще хорошо бы при сборе этих ячеек красить уголки в яркий цвет и задача упросится в разы.

    • Like 1

  12. Basler хорошие камеры. По картинке на порядок лучше  "обычных" ip камеры. Но главное, с точки зрения последующей обработки, отсутствие артефактов от сжатия. 

    Плюс еще много приятностей, типа:

    • довольно быстрое получение кадра, с небольшой нагрузкой на cpu
    • точное время каждого кадра
    • удобный сдк
    • usb подключение (одна fhd GigE камера дает большее 500мбит трафика, две камеры на одной сетевой карте уже будут мешать друг другу),
    • ну и на фоне вебки, сменный объектив, хоть рыбий глаз накручивайте.

    Если бюджет позволяет, то берите.

     


  13. Нет, эффект дисторсии не зависит от расстояния до объекта, но он больше проявляется на краях изображение поэтому лучше что бы тестовое изображение занимало весь кадр.  Если вы не видите дисторсию глазами значит для вашей задачи она не имеет значения.

    Кроме того, на дорогих фиксах ее практически может и не быть, и сама камера может ее исправлять на "борту".

    • Like 1

  14. Сделайте снимок на котором есть вретиакальный и горизонтальные прямые, та-же шахматная доска подойдет. И проверьте являются ли эти линии прямыми на  изображении ,  можно в любом графическом редакторе начертить линию между двумя крайними точками и посмотреть совпадет ли она с изображением. Если искоренения есть то линии будут  кривыми. 

    • Like 1
×