exponenta event banner

Реализация функции потока сбора данных

В этом разделе описывается, как реализовать функцию потока сбора данных адаптера. В конструкции резьбового адаптера функция получения резьбы выполняет фактическое получение кадров от устройства. При создании потока (Открытие и закрытие соединения с устройством) имя этой функции потока сбора данных указывается в качестве начального адреса для нового потока.

Пользовательский сценарий

Механизм панели инструментов вызывает функцию потока сбора данных косвенно, когда пользователь вызывает start, getsnapshot, или preview функция. После вызова функция потока получения получает кадры до тех пор, пока не будет получено заданное количество кадров или пользователь не вызовет stop функция.

Предлагаемый алгоритм

Примечание

Конструкция функции потока сбора данных может значительно варьироваться между различными адаптерами в зависимости от требований SDK устройства. В этом разделе не описываются детали реализации, зависящие от устройства, а описываются необходимые задачи, которые являются общими для всех реализаций.

На своем самом высоком уровне в резьбовой конструкции функция получения резьбы обычно содержит две петли:

Цикл сообщений потока

Цикл сообщений потока является основным циклом обработки в функции потока получения. Вы создаете резьбу в openDevice() функция. Функция потока получения входит в цикл сообщений потока, ожидая, когда сообщение начнет получение кадров. Ваш адаптер startCapture() функция посылает сообщение потоку получения, указывая ему начать получение кадров. В этом примере используется WM_USER сообщение для указания этого состояния. Дополнительные сведения см. в разделе Отправка сообщения в поток сбора данных.

Когда он принимает соответствующее сообщение, функция потока получения входит в цикл получения кадра. На следующем рисунке показано взаимодействие между функциями адаптера и потоком сбора данных. Для получения информации о цикле сбора данных о кадрах см. раздел Цикл сбора данных о кадрах.

Взаимодействие функций адаптера и потока сбора данных

Цикл сбора кадров

Цикл захвата кадров - это место, где адаптер получает кадры от устройства и отправляет их в двигатель. Этот процесс включает в себя следующие этапы:

  1. Проверьте, получено ли указанное количество кадров. Цикл получения кадра получает кадры от устройства до тех пор, пока не будет получено заданное количество кадров. Используйте IAdaptor функция-член isAcquisitionNotComplete() чтобы определить, требуется ли больше кадров.

  2. Если адаптер поддерживает аппаратные триггеры, следует проверить, настроен ли здесь аппаратный триггер - поддержка аппаратных триггеров.

  3. Возьмите рамку из устройства. Этот код полностью зависит от API SDK устройства. При использовании многих SDK устройств выделяется буфер, и устройство заполняет его данными изображения. Ознакомьтесь с документацией по API устройства, чтобы узнать, как получить кадры с устройства.

  4. Проверьте, нужно ли отправлять полученный кадр в двигатель, используя IAdaptor функция-член isSendFrame(). Именно так инструментарий реализует FrameGrabInterval свойство, где пользователи могут указать, что они хотят получить только каждый другой кадр, например.

    Если вам нужно отправить кадр в двигатель, упакуйте кадр в IAdaptorFrame объект; в противном случае перейдите к шагу 5.

    1. Создание объекта-рамки с помощью IEngine объект makeFrame() функция-член. При создании объекта-рамки необходимо указать размеры и тип рамки изображения.

    2. Поместите полученные данные изображения в объект кадра, используя IAdaptorFrame объект setImage() функция-член. Указывается указатель на буфер, содержащий данные изображения, ширину и высоту кадра, а также любые смещения от верхнего левого угла изображения.

      Примечание

      Сведения об указании ширины, высоты и смещения кадра с учетом значений ROI см. в разделе Поддержка значений ROI.

    3. Зарегистрируйте время получения в объекте кадра, используя IAdaptorFrame функция-член setTime(). Комплекты SDK устройств иногда предоставляют доступ к информации о метках времени, но также можно использовать набор адаптеров getCurrentTime() функция.

    4. Отправьте упакованную рамку в двигатель, используя IEngine функция-член receiveFrame().

  5. Увеличьте число кадров с помощью IAdaptor функция-член incrementFrameCount(). Независимо от того, нужно ли посылать кадр или нет, необходимо всегда увеличивать число кадров при каждом получении кадра.

  6. Вернитесь в верхнюю часть цикла захвата кадра.

На следующем рисунке показан цикл захвата кадра.

Возможный алгоритм для цикла получения кадра

Пример

Ниже приводится описание функции потока сбора данных. Вы можете присвоить вашей процедуре потока сбора любое имя, например, acquireThread().

DWORD WINAPI acquireThread(void* ThreadParam);

Функция потока должна принимать один параметр, который определяется как указатель на сам объект, т.е. this указатель. Функция потока возвращает значение, указывающее на успех или сбой. Дополнительные сведения см. в разделе Документы Майкрософт.

Ниже приведена функция потока сбора данных, которую можно использовать в примере MyDeviceAdaptor. Замените каркасную реализацию, использованную при запуске потока сбора данных, этим кодом.

DWORD WINAPI MyDeviceAdaptor::acquireThread(void* param) {

MyDeviceAdaptor* adaptor = reinterpret_cast<MyDeviceAdaptor*>(param);

MSG msg;  
while (GetMessage(&msg,NULL,0,0) > 0) {
    switch (msg.message) {
        case WM_USER:
          // Check if a frame needs to be acquired.
            while(adaptor->isAcquisitionNotComplete()) {

            // Insert Device-specific code here to acquire frames
            // into a buffer.

                if (adaptor->isSendFrame()) {

                    // Get frame type & dimensions.
                    imaqkit::frametypes::FRAMETYPE frameType = 
                                        adaptor->getFrameType();
                    int imWidth = adaptor->getMaxWidth();
                    int imHeight = adaptor->getMaxHeight();

                    // Create a frame object.
                    imaqkit::IAdaptorFrame* frame = 
                            adaptor->getEngine()->makeFrame(frameType,
                                                              imWidth, 
                                                            imHeight);

                    // Copy data from buffer into frame object.
                    frame->setImage(imBuffer,
                                     imWidth,
                                    imHeight,
                                           0, // X Offset from origin
                                           0); // Y Offset from origin

                    // Set image's timestamp.
                    frame->setTime(imaqkit::getCurrentTime());

                    // Send frame object to engine.
                    adaptor->getEngine()->receiveFrame(frame);
                } // if isSendFrame()

            // Increment the frame count.
            adaptor->incrementFrameCount();

            } // while(isAcquisitionNotComplete() 

             break;
        } //switch-case WM_USER
   } //while message is not WM_QUIT
   
return 0;
}