콘텐츠로 건너뛰기

fglib5#

fglib5 라이브러리는 컴퓨터에서 프레임 그래버의 초기화 및 제어를 관리합니다.

라이브러리를 사용하려면 include 파일을 basler_fg.h 소스 코드에 추가해야 합니다.

#include <basler_fg.h>

추가로, fglib5.lib 을(를) Microsoft Visual Studio 프로젝트에 추가해야 합니다. 또는 libfglib5.so 을(를) Linux 프로젝트에 추가합니다. CMake를 사용하는 경우 패키지 이름은 FgLib5입니다. CMake는 include 디렉토리를 다음 변수에 저장합니다. ${FgLib5_INCLUDE_DIR} 및 라이브러리를 다음 변수에 저장합니다. ${FgLib5_LIBRARIES}. 프로젝트 및 CMake 사용 방법에 대한 자세한 내용은 사전 요구 사항 을(를) 참조하십시오.

Frame Grabber Library에서의 에러 처리#

const char * Fg_getErrorDescription(
    Fg_Struct * fg,
    int result);

int Fg_getLastErrorNumber(
    Fg_Struct * fg);

API의 대부분의 함수는 int 결과 코드를 반환합니다. 함수 호출이 성공적으로 실행되면 반환 값은 FG_OK이(가) 됩니다. 음수 값은 대부분의 경우 오류 상태를 나타냅니다. Error Codes은(는) 다음 헤더 파일에 정의되어 있습니다. basler_fg.h.

함수 Fg_getErrorDescription() 을(를) 사용하면 특정 결과 코드의 문자열 표현을 얻을 수 있습니다. 이 함수의 첫 번째 인자인 프레임 그래버 핸들은 사용되지 않으며 API 하위 호환성을 위해서만 포함되어 있습니다. 항상 다음을 전달해야 합니다. nullptr.

함수 Fg_getLastErrorNumber() 은(는) 항상 동일한 스레드 컨텍스트에서 호출된 마지막 함수의 결과 코드를 반환합니다. 이는 함수 자체가 결과 코드를 반환하지 않는 경우에 가장 유용합니다. 이 함수는 인자로 프레임 그래버 핸들을 허용하며, nullptr 마지막으로 호출된 함수가 프레임 그래버 핸들을 수신하지 않은 경우에 사용할 수 있습니다. 프레임 그래버 핸들이 필요한 함수의 결과 코드를 요청하려면 동일한 핸들을 다음으로 전달해야 합니다. Fg_getLastErrorNumber().

정보

Error Codes은(는) 스레드 로컬 스토리지에 저장됩니다. 즉, 다음을 호출하여 Fg_getLastErrorNumber() 응용 프로그램은 하나의 스레드에서 다른 스레드에서 발생한 Error Codes을 요청할 수 없습니다.

다음 코드는 프레임 래퍼 핸들에 특정하지 않은 컨텍스트에서 발생한 마지막 에러와 그 설명을 출력합니다.

int result = Fg_getLastErrorNumber(nullptr);
if (result != FG_OK) {
    const char * description = Fg_getErrorDescription(nullptr, result);

    std::cout << "Error " << result
              << ": " << description
              << std::endl;
}

본 문서의 나머지 부분에 나오는 코드 예제에는 응용 프로그램의 요구 사항에 따라 달라지는 에러 처리가 포함되어 있지 않습니다. 가능한 한 함수가 성공적으로 실행되었는지 확인하기 위해 return codes을 확인합니다.

Frame Grabber Library 초기화#

int Fg_InitLibraries(
    const char *);

void Fg_FreeLibraries();

라이브러리 fglib5를 사용하기 전에 다음 함수를 호출하여 초기화해야 합니다. Fg_InitLibraries(). 이 함수는 내부적인 용도로만 사용되는 인수를 허용하며 nullptr로 설정해야 합니다.

응용 프로그램에서 더 이상 라이브러리를 사용하지 않는 경우 다음 함수를 호출하세요. Fg_FreeLibraries() 이전에 초기화로 인해 할당된 리소스를 해제합니다.

int result = Fg_InitLibraries(nullptr);
if (result != FG_OK) {
    // handle error ...
}

// use frame grabber ...

Fg_FreeLibraries();

시스템 정보#

프레임 래퍼를 초기화하기 전에 사용 중인 Framegrabber API의 버전, 컴퓨터에 설치된 프레임 래퍼의 수 및 유형, 기타 정보를 요청할 수 있습니다.

Framegrabber API 버전#

const char * Fg_getSWVersion();

Framegrabber API의 버전 문자열 표현은 다음을 사용하여 요청할 수 있습니다. Fg_getSWVersion().

const char * rtVersion = Fg_getSWVersion();
std::cout << "Runtime SDK version: " << rtVersion
          << std::endl;

일반 시스템 정보#

int Fg_getIntSystemInformationGlobal(
    Fg_Info_Selector information,
    FgProperty propertyId,
    int * value);

정보

함수 Fg_getIntSystemInformationGlobal() 은(는) Framegrabber API 버전 5.9에 추가되었습니다. 이전 인터페이스에 대한 내용은 섹션 Plain C에서의 시스템 정보 을(를) 참조하십시오.

다음 정보는 다음 함수를 통해 요청할 수 있습니다. Fg_getIntSystemInformationGlobal() 다음 Property을 사용합니다. PROP_ID_VALUE:

정보 설명 Type
INFO_NR_OF_BOARDS 컴퓨터에서 발견된 보드 수 int32_t
INFO_MAX_NR_OF_BOARDS 지원되는 최대 보드 수 int32_t
INFO_SERVICE_ISRUNNING 0: 서비스가 실행 중이 아님; 1: 서비스가 실행 중임 int32_t

예를 들어, 컴퓨터에 설치된 프레임 래퍼의 수는 아래와 같이 요청할 수 있습니다.

int numBoards = 0;
int result = Fg_getIntSystemInformationGlobal(INFO_NR_OF_BOARDS, PROP_ID_VALUE, &numBoards);
if (result == FG_OK) {
    std::cout << "Number of boards: " << numBoards
              << std::endl;
}

보드별 시스템 정보#

int Fg_getIntSystemInformationForBoardIndex(
    unsigned int board,
    Fg_Info_Selector information,
     FgProperty propertyId,
     int * value);

int Fg_getInt64SystemInformationForBoardIndex(
    unsigned int board,
    Fg_Info_Selector information,
    FgProperty propertyId,
    int64_t * value);

int Fg_getStringSystemInformationForBoardIndex(
    unsigned int board,
    Fg_Info_Selector information,
    FgProperty propertyId,
    std::string & value,
    const std::string & arg = "");

int Fg_getIntSystemInformationForFgHandle(
    Fg_Struct * fg,
    Fg_Info_Selector information,
    FgProperty propertyId,
    int * value);

int Fg_getInt64SystemInformationForFgHandle(
    Fg_Struct * fg,
    Fg_Info_Selector information,
    FgProperty propertyId,
    int64_t * value);

int Fg_getStringSystemInformationForFgHandle(
    Fg_Struct * fg,
    Fg_Info_Selector information,
    FgProperty propertyId,
    std::string & value,
    const std::string & arg = "");

정보

이 장에 설명된 함수들은 Framegrabber API 버전 5.9에 추가되었습니다. 이전 인터페이스는 System Information in Plain C 섹션을 참조하십시오.

지정된 프레임 래퍼에 대한 대부분의 다른 정보는 다음 함수를 통해 요청할 수 있습니다. Fg_getIntSystemInformationForBoardIndex(), Fg_getInt64SystemInformationForBoardIndex() 및 Fg_getStringSystemInformationForBoardIndex() 보드 인덱스 또는 프레임 래퍼 핸들과 다음 Property을 사용합니다. PROP_ID_VALUE:

정보 설명 Type
INFO_TIMESTAMP_FREQUENCY 이미지 Timestamp에 사용되는 Timestamp 주파수 int64_t
INFO_BOARDNAME 예: microDiagnostics에 표시되는 보드 이름 string
INFO_BOARDTYPE sisoboards.h에 정의된 보드 유형 int32_t
INFO_BOARDSERIALNO 보드 일련번호 int32_t
INFO_FIRMWAREVERSION 보드의 펌웨어 버전 string
INFO_HARDWAREVERSION 보드의 하드웨어 버전 string
INFO_CAMERA_INTERFACE 보드에서 제공하는 카메라 인터페이스('CameraLink' 또는 'CXP') string
INFO_DRIVERVERSION 보드에 사용되는 드라이버 버전입니다. string
INFO_DRIVERARCH 보드에 사용되는 드라이버 아키텍처입니다. string
INFO_DRIVERFULLVERSION 보드에 사용되는 아키텍처를 포함한 전체 드라이버 버전입니다. string
INFO_DRIVERGROUPAFFINITY 드라이버 IRQ 그룹 친화성(Support for Non-Uniform Memory Access 참조) int32_t
INFO_DRIVERAFFINITYMASK 드라이버 IRQ 프로세서 친화성 마스크(Support for Non-Uniform Memory Access 참조) int64_t
INFO_LICENSE_GROUP_CODE 프레임 그래버 라이선스 그룹 코드 (애플릿 라이선스 그룹 코드의 상위 집합이어야 합니다a) int32_t
INFO_LICENSE_USER_CODE 프레임 그래버 라이선스 사용자 코드 (애플릿 라이선스 사용자 코드와 일치해야 합니다) int32_t
INFO_IS_POCL 0: 보드가 PoCL을 지원하지 않음; 1: 보드가 PoCL을 지원함 int32_t
INFO_NR_OF_CXP_PORTS 'CXP' 인터페이스가 있는 보드의 포트 수입니다. int32_t
INFO_NR_OF_CL_PORTS 'CameraLink' 인터페이스가 있는 보드의 포트 수입니다. int32_t
INFO_NR_OF_PORTS 'CameraLinkHS' 인터페이스가 있는 보드의 포트 수입니다. int32_t
INFO_NR_OF_GIGE_PORTS 'GigE' 인터페이스가 있는 보드의 포트 수입니다. int32_t
INFO_APPLET_DESIGN_ID applet의 HAP ID (applet 경로는 arg 매개변수에 전달되어야 함) string
INFO_APPLET_BITSTREAM_ID applet의 비트스트림 ID (applet 경로는 arg 매개변수에 전달되어야 함) string
INFO_STATUS_PCI_LINK_WIDTH 프레임 그래버에서 사용하는 PCIe 레인 수 int32_t
INFO_STATUS_PCI_EXPECTED_LINK_WIDTH 프레임 그래버에서 지원하는 PCIe 레인 수 int32_t
INFO_STATUS_PCI_LINK_SPEED 프레임 그래버에서 사용하는 PCIe 세대 int32_t
INFO_STATUS_PCI_EXPECTED_LINK_WIDTH 프레임 그래버에서 지원하는 PCIe 세대 int32_t
INFO_STATUS_PCI_PAYLOAD_SIZE 프레임 그래버에서 사용하는 PCIe 페이로드 크기 int32_t

위 목록은 완전하지 않으며 애플리케이션에 유용한 정보에 대한 Property만 포함하고 있습니다. API의 더 많은 사용 사례는 Framegrabber API reference를 참조하십시오.

예를 들어 다음 코드는 보드 유형과 이름을 요청합니다.

const int boardIndex = 0;

int boardType = 0;
int result =
    Fg_getIntSystemInformationForBoardIndex(boardIndex, INFO_BOARDTYPE,
                                            PROP_ID_VALUE, &boardType);

std::string boardName;
if (result == FG_OK) {
    result =
        Fg_getStringSystemInformationForBoardIndex(boardIndex, INFO_BOARDNAME,
                                                   PROP_ID_VALUE, boardName);
}

if (result == FG_OK) {
    std::cout << "Board #" << boardIndex
              << " is a " << boardName
              << " (type " << std::hex << boardType
              << std::dec << ")" << std::endl;
}

초기화 후에 프레임 래퍼 핸들을 사용할 수 있게 되면, 다음 함수들을 사용하여 Fg_getIntSystemInformationForFgHandle(), Fg_getInt64SystemInformationForFgHandle() 및 Fg_getStringSystemInformationForFgHandle() 위 목록에 따라 보드 고유의 정보를 가져오는 데 사용할 수 있습니다. (장 참조 Frame Grabber Initialization.) 프레임 그래버 핸들과 다음 Property를 사용하여 다음 정보를 요청할 수 있습니다. PROP_ID_VALUE:

정보 설명 Type
INFO_APPLET_CAPABILITY_TAGS applet 기능을 설명하는 키-값 쌍 목록 string
INFO_OWN_BOARDINDEX 프레임 그래버의 보드 인덱스 int32_t
INFO_FPGA_BITSTREAM_ID FPGA에서 활성화된 applet의 비트스트림 ID string
INFO_APPLET_FULL_PATH 전체 applet 경로 string
INFO_APPLET_FILE_NAME applet 파일 이름 string
INFO_APPLET_TYPE 0: HAP 파일; 1: DLL/SO 파일 (Applets 참조) int32_t

위의 목록은 완전하지 않으며 응용 프로그램에 유용한 정보에 대한 Property만 포함하고 있습니다. API의 더 많은 사용 사례는 Framegrabber API 레퍼런스를 참조하세요.

보드 인덱스 사용#

보드 인덱스를 사용하여 프레임 래퍼를 선택합니다. 시스템에 있는 보드의 수를 알고 있는 경우, 기본적으로 첫 번째 보드는 인덱스 0, 두 번째 보드는 인덱스 1 등으로 식별됩니다.

Framegrabber API를 사용하면 사용자는 microDiagnostics 내에서 생성할 수 있는 구성 파일을 사용하여 각 보드에 고유한 인덱스를 할당할 수 있습니다. 이 경우 사용자는 자신의 할당 항목과 해당 보드 인덱스를 알고 있어야 합니다.

Applets#

프레임 그래버를 사용하려면 Applet이 필요합니다. Applet은 여러 항목의 모음이며, 일반적으로 다음과 같은 구성 요소로 이루어집니다.

  • 카메라 장치로부터 이미지를 수신하여 처리된 이미지를 컴퓨터 Memory로 전송하는 이미지 처리를 구현하는 프레임 그래버의 FPGA용 디자인
  • 디자인에 사용된 VisualApplets operator와 매개변수를 FPGA 레지스트리에 매핑하기 위한 정보가 포함된 소프트웨어 디자인 설명
  • operator 매개변수 값과 FPGA 레지스트리 콘텐츠 간의 변환을 처리하기 위한 클래스 인스턴스의 생성자 역할을 하는 소프트웨어 인터페이스 라이브러리 모음
  • 모든 operator 클래스 인스턴스화, 초기화 및 Applet과의 인터페이스를 처리하는 최상위 라이브러리인 VAS

Applet은 VisualApplets을 사용하여 디자인된 경우 HAP 파일 형식으로 제공되거나, Framegrabber SDK에 의해 사전 설치된 경우 래핑된 Applet 라이브러리 파일 형식으로 제공됩니다. HAP 파일은 일반적으로 다음의 보드별 하위 디렉터리 내에 저장됩니다. Hardware Applets Framegrabber SDK 설치 디렉터리, 반면 래핑된 Applet 라이브러리 파일은 다음의 보드별 하위 디렉터리에 설치됩니다. dll 디렉터리. 이 문서 전체에서 이러한 하위 디렉터리는 해당 유형의 Applet에 대한 표준 위치로 지칭됩니다.

각 Applet은 제공된 기능을 구성하기 위한 일련의 매개변수를 제공합니다. Applet에서 제공하는 기능과 매개변수에 대한 자세한 내용은 사용할 특정 Applet의 설명서를 참조하십시오.

올바른 Applet 선택#

Framegrabber SDK와 함께 설치할 수 있는 Applet은 일반적으로 래핑된 라이브러리 파일로 제공됩니다. 이러한 파일의 명명 규칙은 몇 가지 규칙을 따릅니다.

  • 파일 이름은 일반적으로 다음으로 시작합니다. Acq_. (이러한 앱릿은 다음과 같이 지칭됩니다.) Advanced Acquisition Applet, 이전 세대는 다음과 같이 지칭되었습니다. Standard Applet , 그리고 명명 규칙이 달랐습니다.)
  • 다음으로, Applet에서 지원하는 카메라 수가 다음 형식으로 표시됩니다. Single, Dual 또는 Quad.
  • 그런 다음 지원되는 카메라 인터페이스가 표시됩니다. 예를 들어, CXP12 은 CoaXPress 표준 버전 2.0에 명시된 대로 최대 12 Gbit/s의 CoaXPress 카메라 인터페이스를 나타냅니다.
  • 구형 프레임 그래버 플랫폼에서는 최대 Camera Link 연결 수가 다음 형식으로 표시됩니다. x1, x2 또는 x4. (이것은 다음이 다음을 지원함에 따라 명명 규칙에서 제외되었습니다. x4 은 다음을 지원하며 x2 및 x1, x2 은 다음을 지원하며 x1 지원되는 최대 링크 수는 지원되는 카메라 수와 프레임 그래버가 제공하는 물리적 포트 수로부터 일반적으로 명확해야 합니다.)
  • 그런 다음 지원되는 센서 유형이 표시됩니다. 이것은 다음 중 하나입니다. Area 또는 Line. 영역형 및 라인형 센서를 모두 지원하는 Applet의 경우 이 항목은 생략됩니다.
  • 이름의 마지막 부분은 다음과 같이 Applet에서 지원하는 데이터 형식입니다. Gray8, Bayer16, RGB24. 여러 데이터 형식을 지원하는 Applet의 경우 이 항목은 생략됩니다.

예를 들어, applet Acq_SingleCXP12Area 은 최대 12 Gbit/s의 CXP 카메라 1대와 면 센서를 지원하는 고급 Acquisition Applet입니다. 이 applet은 다양한 데이터 포맷을 지원합니다. 지원되는 데이터 포맷과 센서 크기를 파악하려면 해당 applet 설명서를 참조해야 합니다.

예를 들어 응용 프로그램에 12 Gbit/s의 CXP 카메라 2대와 10비트 그레이 스케일 출력을 지원하는 라인 타입 센서가 필요한 경우, 다음 이름의 applet을 찾고 Acq_DualCXP12Line, Acq_DualCXP12LineGray10 또는 Acq_DualCXP12LineGray16 동봉된 설명서를 읽어보십시오. 카메라가 단일 물리적 링크만을 사용하여 연결되는 경우, Quad 해당 applet의 변형 버전도 고려할 수 있습니다.

시작 동작#

Framegrabber SDK가 fglib5 라이브러리 초기화를 시작할 때, Frame Grabber Initialization에 설명된 대로 앱릿이 로드되기 전에도 프레임 그래버에 대한 액세스가 필요합니다. 예를 이는 시리얼 번호에 따라 보드를 정렬하거나 로드할 수 있는 모든 앱릿을 확인하는 데 필요합니다.

이 초기화에 사용되는 앱릿은 사용하는 프레임 그래버에 따라 다릅니다. 다음 섹션의 정보를 사용하여 사전 정의된 앱릿으로 시작하도록 프레임 그래버를 구성할 수 있습니다. 사전 정의된 앱릿과 다른 앱릿을 사용하는 경우 호출 Fg_Init 시작 시간이 길어집니다.

시작 시 Framegrabber SDK는 기본적으로 다음 항목에서 사용된 마지막 applet을 로드합니다. Fg_Init.

시스템 환경 변수를 설정하여 이 동작을 비활성화할 수 있습니다. FGSDK_LOAD_LAST_APPLET_ON_INIT=Off.

Start-up Behavior of microEnable 5 marathon Frame Grabbers#

microEnable 5 marathon 프레임 grabber의 경우 사용 가능한 파티션 중 하나에 applet을 보드에 플래시해야 합니다. Framegrabber SDK의 기본 동작은 다음 항목에서 사용된 applet을 설정하는 것입니다. Fg_Init 부팅 파티션으로 설정합니다. 시스템 전원이 켜질 때 부팅 파티션의 applet이 보드를 초기화하는 데 사용됩니다. 이 applet은 Framegrabber SDK의 첫 번째 초기화 단계에서도 사용됩니다.

Start-up Behavior of microEnable 6 Frame Grabbers#

CXP-12 Interface Card, imaWorx CXP-12 Quad, imaFlex CXP-12 Quad 또는 imaFlex CXP-12 Penta 프레임 grabber에서 Framegrabber SDK는 마지막으로 로드된 applet을 열려고 시도합니다. 마지막으로 로드된 applet은 다음 위치에 정의됩니다. LastApplet 섹션의 키 FG 다음 이름의 구성 파일에서 me6_<n>_init.config, 여기서 <n> 은(는) 보드의 드라이버 인덱스입니다. 드라이버 인덱스는 섹션에 설명된 보드 인덱스와 매우 유사하지만 보드 인덱스 사용, 드라이버 전용이며 보드 재정렬의 영향을 받지 않습니다. Windows에서 driver index 0 은 드라이버가 찾은 첫 번째 CXP-12 Interface Card, imaWorx CXP-12 또는 imaFlex CXP-12 프레임 grabber를 나타내며, driver index 1 은 두 번째 보드를 나타내는 식입니다. 다른 모든 운영 체제에서는 재정렬 없이 드라이버 인덱스가 보드 인덱스와 동일합니다.

Windows 시스템에서 구성 파일은 일반적으로 다음 디렉터리에 위치합니다. %APPDATA%\basler. 다른 모든 운영 체제에서 구성 파일은 다음 위치에 있습니다. $HOME/.config/basler 디렉터리. 구성 파일을 찾을 수 없는 경우 Framegrabber SDK는 Framegrabber SDK 설치 루트 폴더를 검색합니다.

프레임 grabber에 대한 구성 파일을 찾지 못했거나 초기화에 실패한 경우 기본 applet이 사용됩니다. 기본 applet은 일반적으로 물리적 포트당 면 센서 타입 카메라 1대를 지원하는 applet입니다.

기본 applet에 대해서도 초기화가 실패하면 Framegrabber SDK는 사용할 수 있는 모든 applet을 엽니다.

Applet 열거#

int Fg_getAppletIterator(
    int board,
    FgAppletIteratorSource source,
    Fg_AppletIteratorType * iter,
    int flags);

Fg_AppletIteratorItem Fg_getAppletIteratorItem(
    Fg_AppletIteratorType iter,
    int index);

int64_t Fg_getAppletIntProperty(
    Fg_AppletIteratorItem item,
    FgAppletIntProperty property);

const char * Fg_getAppletStringProperty(
    Fg_AppletIteratorItem item,
    FgAppletIntProperty property);

int Fg_freeAppletIterator(
    Fg_AppletIteratorType iter);

일반적으로 응용 프로그램은 하나 또는 소수의 특정 applet을 사용하며 기능은 applet 설명서를 통해 파악할 수 있으므로 다음 함수들은 대부분의 응용 프로그램에서 유용하지 않습니다. 응용 프로그램이 더 동적으로 설계된 경우 Framegrabber API는 applet을 열거하고 applet에 대한 다양한 정보를 요청할 수 있는 함수를 제공합니다.

Applet을 열거하려면 다음 함수를 호출할 수 있습니다. Fg_getAppletIterator() . Framegrabber SDK 설치에 사용 가능한 applet을 열거하려면 소스를 FG_AIS_FILESYSTEM 사용해야 합니다. 지정된 보드에 로드할 수 있는 applet만 열거하려면 다음을 전달하십시오. FG_AF_IS_LOADABLE 플래그를 위한 것입니다. 이를 통해 API가 반환하는 모든 applet을 프레임 그래버 초기화를 위한 후속 호출에서 사용할 수 있습니다. 이 함수는 반복자에 있는 항목 수를 반환합니다.

applet 반복자의 항목은 다음을 호출하여 검색할 수 있습니다. Fg_getAppletIteratorItem().

다음 정보를 호출하여 항목에 요청할 수 있습니다. Fg_getAppletIntProperty() 또는 Fg_getAppletStringProperty():

Property 설명 Type
FG_AP_INT_FLAGS 앱릿에 적용되는 플래그(FG_AF_… 상수) int32_t
FG_AP_INT_INFO 앱릿에 적용되는 태그(FG_AI_… 상수) int32_t
FG_AP_INT_PARTITION 앱릿이 플래싱된 파티션(mE5 전용) int32_t
FG_AP_INT_NR_OF_DMA 앱릿에서 제공하는 최대 DMA 채널 수 int32_t
FG_AP_INT_NR_OF_CAMS Applet 사용 시 액세스할 수 있는 최대 카메라 수 int32_t
FG_AP_INT_GROUP_CODE Applet 라이선스 그룹 코드(frame grabber 라이선스 그룹 코드의 하위 집합이어야 함a) int32_t
FG_AP_INT_USER_CODE Applet 라이선스 사용자 코드(frame grabber 라이선스 사용자 코드와 일치해야 함) int32_t
FG_AP_INT_DESIGN_VERSION FPGA 디자인의 주 버전(Major version) int32_t
FG_AP_INT_DESIGN_REVISION FPGA 디자인의 버전 리비전 int32_t
FG_AP_STRING_APPLET_UID Applet 파일을 식별하는 UID string
FG_AP_STRING_BITSTREAM_UID FPGA 디자인을 식별하는 UID string
FG_AP_STRING_DESIGN_NAME FPGA 디자인 이름 string
FG_AP_STRING_APPLET_NAME Applet 이름 string
FG_AP_STRING_DESCRIPTION Applet 설명 string
FG_AP_STRING_CATEGORY Applet 카테고리 string
FG_AP_STRING_APPLET_PATH Applet 전체 경로 string
FG_AP_STRING_SUPPORTED_PLATFORMS 지원되는 플랫폼의 쉼표로 구분된 목록 string
FG_AP_STRING_TAGS 쉼표로 구분된 태그 목록 string
FG_AP_STRING_VERSION Applet 버전 string
FG_AP_STRING_APPLET_FILE Applet 파일 이름 string
FG_AP_STRING_RUNTIME_VERSION 필요한 Framegrabber SDK 버전 string

위의 목록은 완전하지 않으며 응용 프로그램에 유용한 정보에 대한 Property만 포함하고 있습니다. API의 더 많은 사용 사례는 Framegrabber API 레퍼런스를 참조하세요.

applet 반복자를 사용한 후에는 다음을 호출하여 해제해야 합니다. Fg_freeAppletIterator().

이름이 고유하고 applet이 표준 위치 중 한 곳에 있는 경우, applet 이름은 프레임 그래버 초기화를 위한 후속 호출에 충분합니다. 여러 applet이 동일한 이름을 사용하거나 applet이 표준 위치 외부에 있는 경우 전체 경로를 사용해야 합니다. 다음 예제는 표준 위치에서 발견된 모든 applet에서 applet 이름을 추출하는 방법을 보여줍니다.

const in boardIndex = 0;

Fg_AppletIteratorType iter = 0;
int numItems =
    Fg_getAppletIterator(boardIndex, FG_AIS_FILESYSTEM,
                         &iter, FG_AF_IS_LOADABLE);

if (numItems >= 0) {
    std::cout << "Found " << numItems << " applets";

    for (int i = 0; i < numItems; ++i) {
        auto item = Fg_getAppletIteratorItem(iter, i);

        const char * appletName =
            Fg_getAppletStringProperty(item, FG_AP_STRING_APPLET_NAME);

        std::cout << " " << appletName;
    }

    std::cout << std::endl;
    Fg_freeAppletIterator(iter);
}

Frame Grabber Initialization#

Fg_Struct * Fg_Init(
    const char * applet,
    unsigned int board);

int Fg_FreeGrabber(
    Fg_Struct * fg);

프레임 그래버를 사용하려면 먼저 초기화해야 합니다. 이는 다음 함수를 사용하여 applet을 로드함으로써 수행됩니다. Fg_Init(). 이 함수는 지정된 applet으로 프레임 그래버를 초기화한 후 주어진 보드 인덱스에 대한 프레임 그래버 핸들을 반환합니다. 이 핸들은 다음 장에서 설명하는 대부분의 API 함수에서 사용됩니다.

애플리케이션이 프레임 그래버 사용을 마친 후에는 다음을 호출하여 해제해야 합니다. Fg_FreeGrabber().

예를 들어, 다음 코드는 CXP-12 프레임 그래버를 다음 applet으로 초기화합니다. Acq_SingleCXP12Area:

const int boardIndex = 0;
const char * applet = "Acq_SingleCXP12Area";

Fg_Struct * fg = Fg_Init(applet, boardIndex);
if (fg != nullptr) {
    // use frame grabber ...

    Fg_FreeGrabber(fg);
}

구성 파일#

Fg_Struct * Fg_InitConfig(
    const char * config,
    unsigned int board);

int Fg_loadConfig(
    Fg_Struct * fg,
    const char * config);

int Fg_saveConfig(
    Fg_Struct * fg,
    const char * config);

microDisplay X를 사용하여 프레임 그래버를 초기화하고 설정을 테스트하는 경우, 설정은 프로그램 내에서 저장할 수 있습니다. 기본 설정 파일의 확장자는 다음과 같습니다. .mcf 그리고 확장자가 다음과 같은 두 번째 파일이 .mfs 함께 생성됩니다. 이 두 파일을 사용하면 애플리케이션이 API 호출을 통해 설정을 복제하는 대신, 이 두 파일을 사용하여 프레임 그래버를 직접 초기화할 수 있습니다.

이 문맥에서 설정(Configuration)은 프레임 그래버가 초기화된 Applet 및 Applet의 파라미터 설정을 의미합니다. 자세한 내용은 Applet 파라미터 작업하기 단원을 참조하십시오.

정보

함수의 파라미터에는 확장자가 다음과 같은 기본 설정 파일만 .mcf 사용됩니다. 확장자를 제외한 파일 이름이 동일한 한, .mfs 확장자를 가진 파일이 자동으로 사용됩니다.

설정 파일에서 프레임 그래버를 초기화하려면, 함수 Fg_InitConfig() 를 대신 호출할 수 있습니다. Fg_Init(). 이 함수는 지정된 기본 설정 파일에 따라 프레임 그래버를 초기화한 후 주어진 보드 인덱스에 대한 프레임 그래버 핸들을 반환합니다.

애플리케이션이 프레임 그래버 사용을 마친 후에는 다음을 호출하여 해제해야 합니다. Fg_FreeGrabber().

애플리케이션에 서로 다른 설정 세트가 필요한 경우, 다음을 호출하여 언제든지 프레임 그래버에 적용할 수 있습니다. Fg_loadConfig() 호출 후 언제든지 Fg_Init() 또는 Fg_InitConfig().

현재 설정은 다음을 호출하여 설정 파일에 기록할 수 있습니다. Fg_saveConfig() 호출 후 언제든지 Fg_Init() 또는 Fg_InitConfig().

다음 예제는 프레임 그래버의 설정을 저장하고 복원하는 방법을 보여줍니다.

const char * config = "SavedState.mcf";

int result = Fg_saveConfig(fg, config);
if (result != FG_OK) {
    // handle error ...
}

// change frame grabber configuration ...

result = Fg_loadConfig(fg, config);
if (result != FG_OK) {
    // handle error ...
}

Applet 파라미터 작업#

Applet을 사용하여 프레임 grabber가 초기화되면, applet의 파라미터를 읽거나 조작할 수 있습니다. 예를 들어 카메라에서 이미지를 취득하려면, 카메라가 전송하는 이미지 데이터에 따라 올바른 이미지 크기(dimensions)와 Pixel Format을 사용하도록 applet을 구성해야 합니다. 또 다른 예로는 애플리케이션 요구사항에 맞게 applet에서 제공하는 trigger 모듈을 구성하는 것이 있습니다.

파라미터 식별자와 파라미터 이름#

int Fg_getParameterIdByName(
    Fg_Struct * fg,
    const char * name);

const char * Fg_getParameterNameById(
    Fg_Struct * fg,
    unsigned int id,
    unsigned int dma);

FgParamTypes Fg_getParameterTypeById(
    Fg_Struct * fg,
    unsigned int id,
    unsigned int dma);

정보

함수 Fg_getParameterTypeById() Framegrabber SDK 버전 5.9에 추가되었습니다.

applet의 각 파라미터는 이름으로 식별되지만, API는 파라미터 값이나 Property에 액세스하기 위해 숫자 식별자를 사용합니다. 많은 파라미터에는 헤더 파일에 지정된 대로 고정된 숫자 식별자가 있습니다. basler_fg.h, 그러나 가장 일반적인 파라미터를 제외하고는 사용하지 않는 것이 좋습니다. 파라미터의 숫자 식별자를 가져오려면 함수 Fg_getParameterIdByName() 가 사용됩니다. 이 함수는 이름을 식별자로 변환하는 동안 오류가 발생하면 0 또는 음수의 오류 코드를 반환합니다.

숫자 식별자를 알고 있는 파라미터의 이름을 가져오려면 함수 Fg_getParameterNameById() 을(를) 사용할 수 있습니다.

숫자 식별자를 알고 있는 파라미터의 타입을 가져오려면 함수 Fg_getParameterTypeById() 을(를) 사용할 수 있습니다.

파라미터 유형#

Parameter는 형식이 지정되어 있으며, Parameter의 값을 가져오거나 설정하려면 해당 형식을 반드시 알고 있어야 합니다. 형식은 Applet 문서에서 확인하거나, 자체 제작한 VisualApplets Applet을 통해 암묵적으로 파악하거나, 혹은 다음 함수를 사용하여 형식을 요청함으로써 알 수 있습니다. Fg_getParameterTypeById().

파라미터 타입 C/C++ 타입
FG_PARAM_TYPE_INT32_T int32_t
FG_PARAM_TYPE_UINT32_T uint32_t
FG_PARAM_TYPE_INT64_T int64_t
FG_PARAM_TYPE_UINT64_T uint64_t
FG_PARAM_TYPE_DOUBLE double
FG_PARAM_TYPE_CHAR_PTR string
FG_PARAM_TYPE_SIZE_T size_t
FG_PARAM_TYPE_STRUCT_FIELDPARAMINT FieldParameterAccess
FG_PARAM_TYPE_STRUCT_FIELDPARAMINT64 FieldParameterAccess
FG_PARAM_TYPE_STRUCT_FIELDPARAMDOUBLE FieldParameterAccess

필드 Parameter 형식 중 하나를 가진 Parameter는 다음을 사용하여 처리해야 합니다. FG_PARAM_TYPE_STRUCT_FIELDPARAMACCESS 하위 섹션에 설명된 API 필드 파라미터 액세스 챕터 Plain C 사용 시 고려 사항.

파라미터 값 액세스#

int Fg_getParameterWithType(
    Fg_Struct * fg,
    int id,
    int32_t * value,
    unsigned int dma);

// Fg_getParameterWithType() is overloaded for:
//     int32_t * value
//     uint32_t * value
//     int64_t * value
//     uint64_t * value
//     float * value
//     double * value
//     std::string & value
int Fg_setParameterWithType(
    Fg_Struct * fg,
    int id,
    int32_t value,
    unsigned int dma);

// Fg_setParameterWithType() is overloaded for:
//     int32_t value
//     uint32_t value
//     int64_t value
//     uint64_t value
//     float value
//     double value
//     const std::string & value

Parameter의 값을 가져오거나 설정하려면, 오버로드된 함수 Fg_getParameterWithType() 및 Fg_setParameterWithType() 을(를) 사용해야 합니다.

예를 들어, 다음과 같은 Frame grabber 핸들이 주어지면 fg 이전 호출에서 가져온 Fg_Init(), 다음 코드는 Applet의 첫 번째 DMA 채널 너비를 1024로 설정합니다.

const int dma = 0;
const int width = 1024;
int result = FG_INVALID_PARAMETER;

int paramId = Fg_getParameterIdByName(fg, "FG_WIDTH");
if (paramId > 0) {
    result = Fg_setParameterWithType(fg, paramId, width, dma);
}

함수에 전달되는 마지막 파라미터 Fg_getParameterWithType() 및 Fg_setParameterWithType() 대부분의 경우 DMA 채널을 의미합니다. 다음과 같은 매개변수들, 예를 들어 FG_WIDTH, FG_HEIGHT 는 각 DMA 채널마다 다를 수 있으며, 함수에 DMA 채널 번호를 전달하여 이러한 각 파라미터의 인스턴스를 요청하거나 변경할 수 있습니다.

경우에 따라 마지막 Parameter가 다른 논리적 인덱스를 가리킬 수도 있습니다. 예를 들어, 다음과 같은 Parameter가 있습니다. FG_NR_OF_DMAS 또는 FG_NR_OF_CAMS VisualApplets에서 정의된 범위인 applet의 각 프로세스에 대해 여러 인스턴스로 존재합니다.

다른 Parameter들은 Applet 컨텍스트에서 전역(global)이며, 함수 내의 마지막 Parameter는 무시됩니다. 이러한 Parameter 중 하나는 다음과 같습니다. FG_NR_OF_PROCESSES. 그러나 더욱 중요한 점은 애플리케이션 개발자가 VisualApplets를 사용하여 자신만의 applet을 설계하는 경우, applet을 제어하는 모든 파라미터가 고유한 이름으로 식별되므로 전역(global)으로 간주될 수 있으며 함수의 마지막 파라미터는 무시된다는 것입니다.

일부 파라미터는 획득한 이미지마다 다를 수 있으며 DMA 채널과 프레임 번호 또는 버퍼 번호가 모두 필요합니다. 이는 이미지가 컴퓨터 memory로 전송된 시점의 타임스탬프, 실제 이미지 데이터의 길이 및 유사한 정보와 같은 모든 이미지 메타 데이터에 적용됩니다. 이러한 파라미터는 위에서 언급한 함수로 처리할 수 없으며, 이 주제는 Image Acquisition 챕터에서 더 자세히 다룹니다.

파라미터 Property 액세스#

int Fg_getParameterPropertyWithType(
    Fg_Struct * fg,
    int id,
    FgProperty propertyId,
    int32_t * value);

// Fg_getParameterPropertyWithType() is overloaded for:
//     int32_t * value
//     uint32_t * value
//     int64_t * value
//     uint64_t * value
//     float * value
//     double * value
//     std::string & value
int Fg_getParameterPropertyWithTypeEx(
    Fg_Struct * fg,
    int id,
    FgProperty propertyId,
    int32_t * value,
    unsigned int dma);

// Fg_getParameterPropertyWithTypeEx() is overloaded for:
//     int32_t * value
//     uint32_t * value
//     int64_t * value
//     uint64_t * value
//     float * value
//     double * value
//     std::string & value

정보

이 챕터에 문서화된 함수는 Framegrabber SDK 버전 5.9에 추가되었습니다. 이전 인터페이스에 대해서는 Accessing Parameter Properties in Plain C 섹션을 참조하세요.

파라미터는 현재 값 외에도 다양한 Property를 가지고 있습니다. 오버로드된 함수를 사용하여 Fg_getParameterPropertyWithType() 이(가) 권장되지 않는 이유는, 함수 호출이 암묵적으로 DMA 채널 0을 사용하며 채널에 따라 Parameter Property가 다를 수 있기 때문입니다. 오버로드된 함수를 사용하는 것은 Fg_getParameterPropertyWithTypeEx() 다음과 같은 Property를 요청할 수 있습니다.

Property 설명 Type
PROP_ID_VALUE 현재 파라미터 값 파라미터와 동일함
PROP_ID_DATATYPE 파라미터 유형
(FgParamTypes에 따른 열거형 값)
int32_t
PROP_ID_NAME 설명 이름 string
PROP_ID_PARAMETERNAME 파라미터 이름 string
PROP_ID_VALUELLEN 값을 문자열로 인코딩하는 데 필요한 길이 int32_t
PROP_ID_ACCESS 파라미터의 액세스 플래그 int32_t
PROP_ID_MIN 최소 파라미터 값b 파라미터와 동일함
PROP_ID_MAX 최대 파라미터 값b 파라미터와 동일함
PROP_ID_STEP 파라미터의 스텝 크기b 파라미터와 동일함
PROP_ID_IS_ENUM 0: 열거형 파라미터 아님
n: PROP_ID_ENUM_VALUES에 필요한 버퍼 크기
int32_t
PROP_ID_ENUM_VALUES 열거형 값(Accessing the Enum Values Parameter Property 참조) FgPropertyEnumValues[]
PROP_ID_FIELD_SIZE 필드 파라미터의 요소 수 int32_t

위의 목록은 완전하지 않으며 더 이상 사용되지 않는(deprecated) 것으로 간주되지 않는 정보에 대한 Property만 포함하고 있습니다. API의 더 많은 사용 사례는 Framegrabber API 레퍼런스를 참조하십시오.

다음 예제는 paramId가 다음 타입의 파라미터라고 가정할 때 파라미터의 최솟값을 가져오는 방법을 보여줍니다. FG_PARAM_TYPE_INT32_T:

int minVal = 0;
int result =
    Fg_getParameterPropertyWithTypeEx(fg, paramId, PROP_ID_MIN,
                                      &minVal, dma);
if (result == FG_OK) {
    // work with the property ...
}

Memory 관리#

카메라에서 이미지를 획득하려면 이미지를 전송하고 프로그램 내에서 이미지 데이터에 액세스할 수 있도록 컴퓨터에 memory가 필요합니다. Framegrabber API는 원형 버퍼 memory 모델을 사용합니다. memory 버퍼는 프레임 버퍼 또는 서브 버퍼라고도 하는 최소 두 개의 항목으로 구성되며, 카메라에서 획득한 후속 프레임에 재사용됩니다. 사용할 프레임 버퍼 수는 여러 요인에 따라 달라지며, 가장 중요한 요인은 프레임이 처리되는 동안 추가로 도착할 수 있는 프레임 수입니다. 이는 Image Acquisition 챕터의 Acquisition Models 섹션에서 더 자세히 다룹니다.

각 프레임 버퍼는 크기가 동일해야 하며, 일반적으로 너비에 의해 정의되는 애플리케이션 요구사항에 가장 큰 이미지를 저장할 수 있을 만큼 충분히 커야 합니다. FG_WIDTH, 높이(height) FG_HEIGHT 및 Pixel Format FG_FORMAT. (VisualApplets으로 설계된 Applet의 경우, 너비, 높이 및 Pixel Format 설정이 보통 더 복잡합니다.)

원형 버퍼는 가상 주소 공간에서 연속적이며 동일한 크기의 프레임 버퍼로 세분화된 하나의 큰 Memory 블록일 수 있습니다. 또는 Memory에 개별적으로 할당되어 관리 구조에 추가된 프레임 버퍼로 구성될 수도 있습니다. dma_mem API에서 사용됩니다.

void * Fg_AllocMem(
    Fg_Struct * fg,
    size_t totalSize,
    frameindex_t numFrames,
    unsigned int dma);

int Fg_FreeMem(
    Fg_Struct * fg,
    unsigned int dma);

메모리 관리에 사용할 수 있는 세 가지 서로 다른 함수 세트가 있습니다. 그러나 함수 사용 Fg_AllocMem() 및 Fg_FreeMem() 표준 획득 모델(ACQ_STANDARD) 사용으로 제한되므로 권장되지 않습니다. 나머지 두 세트의 함수는 세 가지 획득 모델(ACQ_STANDARD, ACQ_BLOCK, ACQ_SELECT) 모두에서 사용할 수 있고 단순한 사용 사례뿐만 아니라 보다 구체적인 애플리케이션 요구 사항에도 적용할 수 있으므로 여기서 더 자세히 설명합니다.

고급 Memory 관리#

dma_mem * Fg_AllocMemEx(
    Fg_Struct * fg,
    size_t totalSize,
    frameindex_t numFrames);

int Fg_FreeMemEx(
    Fg_Struct * fg,
    dma_mem * mem);

함수 Fg_AllocMemEx() 크기의 커다란 연속 메모리 버퍼 하나를 할당하는 데 사용할 수 있습니다. totalSize 다음으로 세분화됩니다. numFrames 동일한 크기의 프레임 버퍼입니다. 이 함수는 메모리 관리 구조체에 대한 핸들을 반환하며, 오류 발생 시 nullptr을 반환합니다.

반환되는 포인터는 Memory 버퍼 자체에 대한 포인터가 아니므로 직접 사용해서는 안 됩니다! Memory가 더 이상 필요 없어진 후에는 다음을 사용하여 해제해야 합니다. Fg_FreeMemEx().

다음 예제에서 코드는 1024 x 1024 크기의 24비트 RGB 이미지를 저장할 수 있는 16개의 프레임 버퍼에 대한 메모리 버퍼를 할당합니다:

const int width = 1024, height = 1024;
const int bytesPerPixel = 3;
const frameindex_t numFrames = 16;
const size_t frameSize = static_cast<size_t>(width) * height * bytesPerPixel;
const size_t totalSize = frameSize * numFrames;

dma_mem * mem = Fg_AllocMemEx(fg, totalSize, numFrames);
if (mem != nullptr) {
    // use memory, acquire and process images ...

    Fg_FreeMem(fg, mem);
}

이 static_cast<size_t>(width) 계산 시 frameSize. 이는 매우 큰 이미지의 크기가 올바르게 계산되도록 하기 위해 필요합니다.

유연한 Memory 관리#

dma_mem * Fg_AllocMemHead(
    Fg_Struct * fg,
    size_t totalSize,
    frameindex_t numFrames);

int Fg_AddMem(
    Fg_Struct * fg,
    void * frameBuffer,
    size_t size,
    frameindex_t index,
    dma_mem * mem);

int Fg_DelMem(
    Fg_Struct * fg,
    dma_mem * mem,
    frameindex_t index);

int Fg_FreeMemHead(
    Fg_Struct * fg,
    dma_mem * mem);

응용 프로그램이 Framegrabber API가 처리하도록 하는 대신 메모리 할당에 대한 특정 요구 사항이 있는 경우, 함수 Fg_AllocMemHead() Memory 관리 구조를 준비하는 데 사용할 수 있습니다. 이 함수는 다음와 동일한 파라미터를 요구합니다. Fg_AllocMemEx(), 그러나 메모리는 할당되지 않습니다. 응용 프로그램에서 메모리를 할당한 후, 각 프레임 버퍼는 함수를 사용하여 개별적으로 추가되어야 합니다. Fg_AddMem(). 애플리케이션에서 획득 실행 중 Memory 버퍼에 사용되는 프레임 버퍼의 동적 변경이 필요한 경우, 함수 Fg_DelMem() can be used to remove frame buffers from the memory buffer. After the memory buffer is no longer needed, the management structure should be released first by calling Fg_FreeMemHead() 프레임 버퍼용 Memory를 해제하기 전에.

다음 코드는 'Fg_AllocMemEx()' 함수가 더 유연한 메모리 관리 API를 위한 편의 래퍼인 방법을 보여줍니다.

int Fg_AllocMemEx(Fg_Struct * fg, size_t totalSize, frameindex_t numFrames)
{
    const size_t frameSize = totalSize / numFrames;
    char * buf = nullptr;

    dma_mem * mem = Fg_AllocMemHead(fg, totalSize, numFrames);
    if (mem != nullptr) {
        try {
            buf = new char[totalSize];
            for (frameindex_t frame = 0; frame < numFrames; ++frame) {
                const int result =
                    Fg_AddMem(fg, buf + frameSize*frame,
                              frameSize, frame, mem);
                if (result != FG_OK) {
                    throw std::runtime_error("Failed to add frame buffer");
                }
            }
        }
        catch (...) {
            for (frameindex_t frame = 0; frame < numFrames; ++frame) {
                Fg_DelMem(fg, mem, frame);
            }
            Fg_FreeMemHead(fg, mem);
            delete[] buf;
            return nullptr;
        }
    }
    return mem;
}

이미지 취득#

Framegrabber API는 세 가지 서로 다른 취득 모델과 결합할 수 있는 두 가지 이미지 데이터 전달 모드를 제공합니다.

이미지 데이터는 동기 모드 또는 비동기 모드로 전달될 수 있습니다. 동기 모드에서는 애플리케이션에서 획득 루프를 제공해야 합니다. 비동기 모드에서는 새 이미지 데이터를 사용할 수 있게 될 때마다 호출될 콜백 함수를 등록할 수 있습니다. Framegrabber API는 비동기 모드를 위해 별도의 스레드에서 이미지 획득 루프를 제공합니다. 일부 GUI 프레임워크의 경우 Framegrabber API 스레드 컨텍스트를 GUI 스레드 컨텍스트로 다시 동기화하는 작업이 복잡할 수 있으며, 프레임워크에서 제공하는 스레드 컨텍스트에서 획득 루프를 실행하는 것이 더 합리적일 수 있습니다.

비동기 모드용 콜백 함수 등록#

typedef int (* Fg_ApcFunc_t)(
    frameindex_t frame,
    void * data);

int Fg_registerApcHandlerEx(
    Fg_Struct * fg,
    unsigned int dma,
    Fg_ApcFunc_t func,
    void * data,
    unsigned int timeout,
    unsigned int flags);

int Fg_unregisterApcHandler(
    Fg_Struct * fg,
    unsigned int dma);

정보

Framegrabber API 버전 5.9에서 함수 Fg_registerApcHandlerEx() 및 Fg_unregisterApcHandler() 추가되었으며 차단 획득 모델을 사용할 때의 동작은 ACQ_BLOCK 변경되었습니다. 섹션 참조 Plain C에서 비동기 모드를 위한 콜백 함수 등록 을(를) 참조하십시오.

함수 Fg_registerApcHandlerEx() 획득을 시작하기 전에 비동기 모드를 설정하는 데 사용할 수 있습니다.

사용 Fg_registerApcHandlerEx(), 다음 유형의 함수 Fg_ApcFunc_t 이미지 데이터가 수신될 때 호출되도록 등록할 수 있습니다. 이 함수는 지정된 프레임 그래버 및 DMA 채널에 대해 등록되며 호출 시 두 개의 매개변수가 전달됩니다. 콜백 함수의 첫 번째 매개변수는 프레임 번호입니다(위치: ACQ_STANDARD 및 ACQ_SELECT) 또는 버퍼 번호 ( ACQ_BLOCK) 수신된 이미지에 대한 것입니다. 두 번째 매개변수는 다음 호출 시 제공된 포인터입니다. Fg_registerApcHandlerEx() 그리고 컨텍스트 구조체나 클래스에 대한 포인터로 사용할 수 있습니다. 예: this 이미지 처리를 구현하는 클래스 인스턴스의 포인터입니다.

지정된 프레임 그래버의 각 DMA 채널에 대해 하나의 콜백 함수만 등록할 수 있습니다.

콜백 함수는 Framegrabber API에서 제공하는 획득 루프에서 호출됩니다. 이는 콜백 함수가 획득 루프의 스레드 컨텍스트에서 호출됨을 의미합니다. 또한 콜백 함수가 반환될 때까지 걸리는 시간이 획득 루프의 일반적인 관리 오버헤드에 추가되며, 이 시간 동안 여러 이미지가 수신되었을 수 있음을 의미합니다. 그 시간 동안 이미지가 수신된 경우, 콜백 함수는 반환 직후에 즉시 다시 호출됩니다.

이미지 취득 처리는 다음을 통해 제어할 수 있습니다. timeout 및 flags 호출 시의 파라미터 Fg_registerApcHandlerEx(). 타임아웃은 취득 루프가 새 이미지가 도착할 때까지 대기해야 하는 시간을 초 단위로 지정합니다. 매개변수의 경우 flags, 다음 값과 이들의 조합을 연산자와 결합 | (비트 OR)를 사용할 수 있습니다.

Flag 설명
FG_APC_DEFAULTS 수집 루프에서의 기본 처리
FG_APC_BATCH_FRAMES 여러 장의 이미지가 수신된 경우 콜백 함수의 단일 호출에서 가장 최신의 이미지마저 전달될 수 있습니다.
FG_APC_DELIVER_ERRORS 콜백 함수에 에러를 음수의 frameindex_t 값으로 전달합니다.
FG_APC_IGNORE_TIMEOUTS 이미지 타임아웃을 무시하고 처리를 계속합니다.
FG_APC_IGNORE_APCFUNC_RETURN 콜백 반환 값을 무시하고 처리를 계속합니다.
FG_APC_IGNORE_STOP 수집이 중지된 시점을 무시하고 처리를 계속합니다.
FG_APC_HIGH_PRIORITY 수집 루프를 구현하는 스레드의 우선순위를 높입니다. 이 값을 사용하려면 운영 체제의 관리자 권한이 필요합니다.
FG_APC_OLD_ACQ_BLOCK_BEHAVIOR 사용 대상: Fg_getLastPicNumberBlockingEx() ACQ_BLOCK 내c

취득 루프의 기본 처리는 다음과 같습니다.

  • 모든 단일 이미지가 콜백 함수에 전달됩니다.
  • 에러 값은 콜백 함수로 전달되지 않습니다.
  • 이미지 타임아웃이 취득 루프를 종료합니다.
  • 콜백 함수의 0이 아닌 반환 값은 획득 루프를 종료합니다.
  • 취득 중지가 취득 루프를 종료합니다.
  • 획득 루프는 기본 우선순위를 가진 스레드에서 실행됩니다.
  • 함수 Fg_getLastPicNumberBlockingEx() 호출되며, 그 결과는 콜백 함수로 전달됩니다.

정보

획득 루프를 종료하면 콜백 함수가 자동으로 등록 해제됩니다. 획득이 중지될 때 항상 획득 루프를 종료하는 것이 당연해 보일 수 있지만, 항상 그런 것은 아닙니다. 예를 들어 애플리케이션에서 Fg_AcquireEx를 획득할 유한한 프레임 수와 함께 호출하여 특정 수의 이미지 버스트로 획득을 실행해야 하는 경우를 생각해 보세요. 지정된 수의 프레임이 획득된 후 드라이버에 의해 획득이 자동으로 중지됩니다. 획득 루프를 계속 실행 상태로 유지하고 별도의 스레드에서 획득 버스트를 시작하는 것이 편리할 수 있습니다.

정보

Setting FG_APC_HIGH_PRIORITY 프로세스가 스레드 우선순위를 변경할 수 있는 필수 권한을 가지고 있는 경우에만 가능합니다. 사용하는 운영 체제의 권한 및 권리 관리 문서를 참조하세요. Microsoft Windows를 사용하는 애플리케이션의 경우 함수 SetThreadPriority 사용됩니다. Linux에서는 함수 pthread_setschedparam 가 사용됩니다.

다음 예제는 이미지 수집 처리에 필요한 정보를 담고 있는 간단한 구조체를 사용하여 콜백 함수를 등록하는 방법을 보여줍니다.

struct ApcUserCallbackData
{
    Fg_Struct * fg;
    dma_mem * mem;
    unsigned int dma;
    unsigned int timeoutInSeconds;
    int mode;
};

int ApcUserCallback(frameindex_t frame, void * data)
{
    auto context = reinterpret_cast<ApcUserCallbackData *>(data);

    if (frame > 0) {
        // process new image ...
    } else {
        // handle error ...
    }

    return 0;
}

void SetupApcUserCallback(ApcUserCallbackData * context)
{
    // register callback function
    int result =
        Fg_registerApcHandlerEx(
            context->fg,
            context->dma,
            &ApcUserCallback,
            context,
            context->timeoutInSeconds,
            FG_APC_DELIVER_ERRORS | FG_APC_IGNORE_TIMEOUTS);
    if (result != FG_OK) {
        throw std::runtime_error("Failed to register callback function");
    }
}

컨텍스트 구조의 할당 및 관리는 예제에 표시되지 않습니다. 포인터는 콜백 함수가 등록되어 있는 동안 유효해야 합니다. 한 가지 해결책은 C++ 클래스 내에서 모든 것을 함께 유지하는 것입니다. C++ 클래스 컨텍스트에서 콜백 함수를 사용하려면 정적 함수를 사용하여 콜백 핸들러를 등록할 수 있으며, this 포인터는 컨텍스트 데이터 포인터로 사용되어야 하며, 이를 다시 클래스 포인터로 캐스팅하여 그에 따라 사용할 수 있습니다.

콜백 함수가 더 이상 필요하지 않게 되면 다음을 호출하여 등록을 해제할 수 있습니다. Fg_unregisterApcHandler() 동일한 frame grabber 핸들과 DMA 채널을 사용합니다:

Fg_unregisterApcHandler(context->fg, context->dma);

취득 시작#

프레임 그래버에서 애플리케이션 Memory으로의 이미지 데이터 전송을 활성화하려면 앱릿에서 취득을 시작해야 합니다. 이를 통해 프레임 그래버는 이미지 데이터가 전송될 프레임 버퍼에 대해 알게 되며, 새 이미지의 데이터 전송이 성공적으로 완료될 때마다 드라이버에 인터럽트를 보낼 수 있게 됩니다. 대부분의 경우 프레임 그래버 측에서 취득을 시작한 후 카메라 측에서도 취득을 시작하고 카메라 트리거를 시작해야 합니다.

카메라 제어에 대한 자세한 내용은 The Camera Control Library siso_genicam 또는 The Camera Link Serial Interface Library clsersis를 참조하세요. 카메라 트리거는 이 문서의 범위를 벗어나지만, 애플릿 문서는 소프트웨어 또는 하드웨어 신호를 통해 프레임 그래버로 카메라를 트리거하기 위해 애플리케이션에 있는 옵션에 대한 자세한 정보를 제공합니다.

int Fg_Acquire(
    Fg_Struct * fg,
    unsigned int dma,
    frameindex_t frames);

int Fg_stopAcquire(
    Fg_Struct * fg,
    unsigned int dma);

함수 Fg_Acquire() 및 Fg_stopAcquire() memory management 함수와 조합하여서만 사용할 수 있습니다. Fg_AllocMem() 및 Fg_FreeMem() 및는 표준 수집 모델 사용으로 제한됩니다. ACQ_STANDARD. 이러한 함수들의 사용은 권장되지 않으며 문서화되지 않습니다. 대신 다음 함수들을 사용하십시오. Fg_AcquireEx() 및 Fg_stopAcquireEx() 을(를) 사용해야 합니다.

고급 또는 유연한 Memory 관리를 사용한 Image Acquisition#
int Fg_AcquireEx(
    Fg_Struct * fg,
    unsigned int dma,
    frameindex_t frames,
    int flags,
    dma_mem * mem);

int Fg_stopAcquireEx(
    Fg_Struct * fg,
    unsigned int dma,
    dma_mem * mem,
    int flags);

함수 Fg_AcquireEx() 을(를) 호출하여 프레임 그래버의 단일 DMA 채널에서 이미지 수집을 시작할 수 있습니다. 이 호출은 DMA 채널을 연결하며 dma memory handle로 mem 따라서 이미지 데이터를 수신하기 위해 할당된 메모리를 사용하게 됩니다.

취득은 파라미터를 통해 지정된 프레임 수에 도달할 때까지 frames 에 도달합니다. 만약 GRAB_INFINITE 전달됩니다. frames인 경우, 수집은 무기한 실행됩니다. 매개변수를 통해 flags, acquisition 모델을 선택할 수 있습니다. 자세한 내용은 다음 섹션을 참조하십시오. Acquisition Models .

모델 설명
ACQ_STANDARD 프레임 버퍼 보호가 없는 연속 acquisition
ACQ_BLOCK 프레임 버퍼 차단이 있는 연속 acquisition
ACQ_SELECT 수동 프레임 버퍼 처리를 사용하는 완전 애플리케이션 제어 acquisition

에 수집할 프레임 수를 지정할 때 Fg_AcquireEx()Framegrabber SDK가 예상된 수의 프레임을 감지하면 수집이 자동으로 중지됩니다. 경우에 따라 이는 마지막 프레임을 처리할 때 예상치 못한 동작으로 이어질 수 있습니다. 이를 방지하려면 수집 모델 외에도 ACQ_NO_AUTOSTOP 파라미터에서 지정할 수 있습니다. flags. 언제 ACQ_NO_AUTOSTOP 이(가) 사용되는 경우, 요청된 프레임 수에 도달하면 드라이버는 프레임 취득을 중지하지만 Framegrabber SDK의 나머지 부분과 프레임 그래버는 Fg_stopAcquireEx() 이(가) 호출될 때까지 취득 모드 상태를 유지합니다.

수집을 중지하고 사용된 애플릿의 실행 상태를 재설정하려면 함수 Fg_stopAcquireEx() 을(를) 호출해야 합니다. 매개변수를 통해 flags, 정지 모드를 선택할 수 있습니다:

Mode 설명
STOP_ASYNC acquisition 즉시 중지
STOP_SYNC_TO_APC 비동기 모드에서 acquisition 중지를 콜백 함수에 동기화
콜백이 완료될 때까지 대기하는 시간(밀리초)은 FG_APC_STOP_TIMEOUT 파라미터를 사용하여 설정할 수 있습니다.
STOP_SYNC acquisition 중지를 드라이버와 동기화
다음 이미지 전송이 완료될 때까지 대기하는 시간(초)은 FG_STOP_TIMEOUT 파라미터를 사용하여 설정할 수 있습니다.
STOP_ASYNC_FALLBACK STOP_SYNC와 함께 사용할 수 있으며
중지를 동기화할 수 없는 경우 STOP_ASYNC로 대체됩니다.

동기 모드용 취득 루프 작성#

동기 모드에서는 애플리케이션이 새 이미지 수신을 처리해야 합니다. 이는 일반적으로 특정 DMA 채널에서 새 이미지 전송을 대기하는 Framegrabber API에서 제공하는 함수 중 하나를 호출하는 acquisition 루프 형태로 수행됩니다. 사용할 함수를 이해하려면 Acquisition Models 섹션을 참조하십시오. 각 모델에 대한 예제 acquisition 루프는 해당 하위 섹션에 나와 있습니다.

frameindex_t Fg_getLastPicNumberBlocking(
    Fg_Struct * fg,
    frameindex_t frame,
    unsigned int dma,
    int timeout);

함수 Fg_getLastPicNumberBlocking() 함수와 조합하여서만 사용할 수 있습니다. Fg_Acquire() 표준 취득 모델로 제한됩니다 ACQ_STANDARD. 이 함수의 사용은 권장되지 않으며 문서화되지 않습니다. 대신 다음 함수들을 사용하십시오. Fg_getLastPicNumberBlockingEx() 또는 Fg_getImageEx() 을(를) 사용해야 합니다.

고급 또는 유연한 Memory 관리를 사용하여 이미지 대기#
frameindex_t Fg_getLastPicNumberBlockingEx(
    Fg_Struct * fg,
    frameindex_t frame,
    unsigned int dma,
    int timeout,
    dma_mem * mem);

frameindex_t Fg_getImageEx(
    Fg_Struct * fg,
    int strategy,
    frameindex_t frame,
    unsigned int dma,
    unsigned int timeout,
    dma_mem * mem);

함수 Fg_getLastPicNumberBlockingEx() 파라미터에 요청된 프레임을 대기합니다 frame 파라미터에 지정된 초 내에 도달하도록 timeout 파라미터에 지정된 특정 DMA 채널에서 dma. 첫 번째 프레임 번호는 0이 아니라 1입니다. 이 함수는 성공 시 0보다 큰 프레임 번호를 반환하고, 실패 시 음수 에러 코드를 반환합니다.

정보

반환된 프레임 번호는 함수가 항상 사용 가능한 최신 프레임 번호를 반환하므로 요청된 프레임 번호보다 클 수 있습니다. 즉, 함수를 두 번 호출하는 사이에 둘 이상의 프레임이 도착했을 수 있으며 애플리케이션은 최신 프레임만 처리할지 모든 프레임을 처리할지 결정해야 합니다.

다음 예제는 다음을 위한 간단한 취득 루프를 보여줍니다: ACQ_STANDARD:

const int timeoutInSeconds = 10;

frameindex_t nextFrame = 1;
while (true) {
    // get new image
    const frameindex_t newestFrame =
        Fg_getLastPicNumberBlockingEx(fg, nextFrame, dma,
                                      timeoutInSeconds, mem);

    if (newestFrame > 0) {
        // process new images ...

        nextFrame = (newestFrame < FRAMEINDEX_MAX) ? newestFrame + 1 : 1;
    } else {
        // handle error ...
    }
}

함수 Fg_getImageEx() 훨씬 더 복잡합니다. 함수의 동작과 성공 시 반환 코드의 의미는 파라미터에 따라 다릅니다. strategy 및 timeout 그리고 사용 중인 acquisition 모델에 따라 다릅니다. 오류가 발생한 경우 결과는 항상 음수 오류 코드가 됩니다. 다양한 전략에 대한 간략한 설명은 아래에 제공되지만, 일반적으로 이 함수의 사용은 다음 섹션에 설명된 사용 사례로 제한되어야 합니다. The Blocking Acquisition Model. 이 함수를 다른 용도로 사용하는 것은 권장되지 않으며 이 문서에서는 더 이상 자세히 설명하지 않습니다.

SEL_NEW_IMAGE: 이 함수는 타임아웃을 지정해야 하며 최소한 하나의 새 이미지가 도착할 때까지 대기합니다. ACQ_STANDARD 및 ACQ_SELECT 최신 이미지의 프레임 번호가 반환됩니다. ACQ_BLOCK, 이 함수는 최신 이미지에 대한 프레임 버퍼를 차단하고, 추가 이미지의 프레임 버퍼 차단을 해제하며, 차단된 이미지의 버퍼 번호를 반환합니다.

SEL_NEXT_IMAGE: 대상 ACQ_STANDARD타임아웃이 지정되지 않은 경우, 함수는 수신된 최신 이미지의 버퍼 번호를 반환합니다. 타임아웃이 지정된 경우, 함수는 이전에 함수를 호출했을 때 수신된 마지막 프레임 이후의 다음 프레임(함수를 이전에 호출하지 않은 경우 프레임 번호 1)을 대기합니다. 함수는 수신된 최신 이미지의 프레임 번호를 반환합니다. ACQ_BLOCK, 이 함수는 아직 차단되거나 차단 해제되지 않은 수신된 첫 번째 이미지의 프레임 버퍼를 차단하고 차단된 이미지의 버퍼 번호를 반환합니다. 더 이상 이미지를 차단할 수 없고 타임아웃이 지정된 경우, 함수는 차단 작업을 수행하기 전에 최소한 하나의 새 이미지가 도착할 때까지 대기합니다.

SEL_ACT_IMAGE: 대상 ACQ_STANDARD, 이 함수는 다음의 경우와 동일하게 작동합니다. SEL_NEXT_IMAGE 이 지정됩니다. ACQ_BLOCK, 이 함수는 최신 이미지에 대한 프레임 버퍼를 차단하고, 추가 이미지의 프레임 버퍼 차단을 해제하며, 차단된 이미지의 버퍼 번호를 반환합니다. 더 이상 차단할 수 있는 이미지가 없고 타임아웃이 지정된 경우, 이 함수는 차단 작업을 수행하기 전에 적어도 하나 이상의 새 이미지가 도착할 때까지 대기합니다.

SEL_LAST_IMAGE: 이 함수는 함수에서 반환된 마지막 값을 반환하거나, Fg_getLastPicNumberBlockingEx(). 이는 마지막 함수 호출 방식에 따라 마지막 프레임 번호 또는 버퍼 번호 중 하나가 됩니다.

SEL_NUMBER: 이 함수는 다음의 동작을 모방합니다. Fg_getLastPicNumberBlockingEx().

다음 예제는 다음을 위한 간단한 취득 루프를 보여줍니다: ACQ_BLOCK 사용 SEL_NEXT_IMAGE (취득된 모든 이미지가 처리됨):

const int timeoutInSeconds = 10;

while (true) {
    // get new image
    const frameindex_t buffer =
        Fg_getImageEx(fg, SEL_NEXT_IMAGE, 0, dma, timeoutInSeconds, mem);

    if (buffer > 0) {
        // process new image ...
    } else {
        // handle error ...
    }
}

드라이버 이미지 취득 타임아웃 FG_TIMEOUT#

함수를 호출할 때 이미지 대기 시간을 지정하는 것 외에도 Fg_getImageEx() 또는 Fg_getLastPicNumberBlockingEx(), 또는 비동기 모드용 콜백 함수를 설정할 때 드라이버는 이미지 전송 인터럽트 처리 컨텍스트 내에서 이미지 Acquisition Status도 추적합니다. 매개변수에서 지정된 초 동안 이미지 데이터가 수신되지 않으면 드라이버는 이미지 Acquisition을 중지합니다. FG_TIMEOUT. FG_TIMEOUT 로 설정된 경우, FG_TIMEOUT_INFINITE (값 FG_TIMEOUT_INFINITE 인 경우 INT_MAX - 1) 두 이미지 수신 사이의 시간 간격에 관계없이 드라이버는 Acquisition을 중지하지 않습니다.

파라미터 FG_TIMEOUT 의 값은 취득이 시작될 때 드라이버로 전달됩니다. 취득 시작 후 파라미터가 변경되면 취득이 중지되고 다시 시작될 때까지 드라이버에 반영되지 않습니다.

드라이버가 Acquisition을 중지한 후, 여전히 이미지를 대기 중인 모든 함수 호출은 다음을 반환합니다. FG_TIMEOUT_ERR 그리고 취득이 중지된 후 이미지 대기를 위해 호출된 모든 함수는 반환합니다 FG_TRANSFER_NOT_ACTIVE.

정보

매개변수의 기본값 FG_TIMEOUT 인 경우 포함되지 FG_TIMEOUT_INFINITE, 그러나 대부분의 경우 1,000,000초(약 277시간 46분에 해당)로 설정됩니다. 매개변수를 명시적으로 설정하는 것이 좋습니다. FG_TIMEOUT (으)로 FG_TIMEOUT_INFINITE 취득을 시작하기 전에.

다음 예제는 드라이버 이미지 Acquisition 타임아웃을 비활성화하는 방법을 보여줍니다.

Fg_setParameterWithType(fg, FG_TIMEOUT, FG_TIMEOUT_INFINITE, dma);

프레임 및 Acquisition 정보#

int Fg_getParameterEx(
    Fg_Struct * fg,
    int param,
    void * value,
    unsigned int dma,
    dma_mem * mem,
    frameindex_t frame);

void * Fg_getImagePtrEx(
    Fg_Struct * fg,
    frameindex_t frame,
    unsigned int dma,
    dma_mem * mem);

frameindex_t Fg_getStatusEx(
    Fg_Struct * fg,
    int status,
    frameindex_t frame,
    unsigned int dma,
    dma_mem * mem);

수신된 각 프레임에 대해 다음 정보를 요청하려면 함수를 호출하면 됩니다 Fg_getParameterEx():

Parameter 설명 Type
FG_TRANSFER_LEN 전송된 실제 바이트 수 size_t
FG_TIMESTAMP_LONG 이미지의 고해상도 Timestamp uint64_t
FG_TIMESTAMP_LONG_FREQUENCY 고해상도 Timestamp 주파수 uint64_t
FG_TIMESTAMP 밀리초 단위의 이미지 Timestamp uint32_t
FG_IMAGE_TAG 이미지 태그 uint32_t
FG_IMAGE_NUMBER 프레임 번호 uint64_t

정보

프레임 번호 정보는 Framegrabber SDK 버전 5.9에 추가되었습니다.

각 프레임에 대한 정보는 무기한 사용할 수 있는 것은 아니며, 해당 버퍼가 후속 전송을 위해 대기열에 추가되지 않은 상태에서만 유효합니다. 사용된 acquisition 모델에 따라 이 함수에는 프레임 번호나 버퍼 번호가 필요합니다. 자세한 내용은 Acquisition Models 섹션을 참조하십시오.

다음 예제는 특정 프레임에 대한 Timestamp를 요청하는 방법을 보여줍니다:

// get time stamp frequency
uint64_t frequency = 0;
Fg_getParameterEx(fg, FG_TIMESTAMP_LONG_FREQUENCY, &frequency, 0, nullptr, 0);

// ...

// get frame time stamp
uint64_t timestamp = 0
int result =
    Fg_getParameterEx(fg, FG_TIMESTAMP_LONG, &timestamp, dma, mem, frame);
if (result == FG_OK) {
    // this will probably be 'seconds since booting the computer' ...
    // it makes more sense when you calculate the difference
    // between timestamps of two frames
    double seconds =
        static_cast<double>(timestamp)/static_cast<double>(frequency);

    // ...
}

프레임 버퍼에 대한 포인터를 가져오려면 함수 Fg_getImagePtrEx() 을(를) 호출할 수 있습니다. 각 프레임에 대한 포인터는 무기한 사용할 수 있는 것은 아니며, 해당 버퍼가 후속 전송을 위해 대기열에 추가되지 않은 상태에서만 유효합니다. 사용된 acquisition 모델에 따라 이 함수에는 프레임 번호나 버퍼 번호가 필요합니다. 섹션 참조: Acquisition Models 자세한 내용은 을 참조하십시오.

다음 예제는 특정 프레임에 대한 frame buffer 포인터를 요청하는 방법을 보여줍니다.

// get a pointer to the frame buffer for the newest image
void * buffer = Fg_getImagePtrEx(fg, frame, dma, mem);

// get the actual number of bytes transferred
size_t length = 0;
int result =
    Fg_getParameterEx(fg, FG_TRANSFER_LEN, &length, dma, mem, frame);

if ((buffer != nullptr) && (result == FG_OK) && (length > 0)) {
        // process image data ...
}

함수 Fg_getStatusEx() 을(를) 호출하여 다음 일반 상태 정보를 요청할 수 있으며, 매개변수 frame 다음 항목에서는 무시됩니다.

Status 설명
NUMBER_OF_GRABBED_IMAGES 전송된 총 프레임 수
NUMBER_OF_LAST_IMAGE 보고된 마지막 프레임 번호 Fg_getLastPicNumberBlockingEx()
NUMBER_OF_NEXT_IMAGE 보고된 마지막 프레임 다음 프레임의 번호
GRAB_ACTIVE 0: DMA 채널이 활성화되지 않음
1: DMA 채널이 활성화됨

다음 예제는 DMA 채널의 Acquisition Status를 요청하는 방법을 보여줍니다.

frameindex_t active =
    Fg_getStatusEx(fg, GRAB_ACTIVE, 0, dma, mem);
if (active == 1) {
    // the DMA channel is active ...
} else if (active == 0) {
    // the DMA channel is inactive ...
} else {
    // handle error ...
}

Acquisition Models#

Framegrabber API는 세 가지 서로 다른 Acquisition Model을 제공하며, 호출 시 선택할 수 있습니다. Fg_AcquireEx(): 표준, 차단형, 선택형. 이 세 가지 acquisition 모델은 다음 장에서 설명하는 memory 모델을 기반으로 합니다. Memory 관리 이미지 acquisition을 위해 최소 두 개의 프레임 버퍼를 사용합니다.

이 섹션의 예제에서는 가상 메모리에서 연속적인 네 개의 frame buffer로 구성된 memory buffer가 사용됩니다.

Memory Buffer Model

Frame Numbers and Buffer Numbers#

Framegrabber API 전반에 걸쳐 프레임 번호와 버퍼 번호가 사용되며, 두 가지 모두 유형입니다. frameindex_t.

Frame number는 다음 범위 내에서 엄격하게 단조 증가하는 자연수이지만 [1; FRAMEINDEX_MAX], Acquisition이 시작된 이후 획득한 이미지의 수를 나타내며, 유형 frameindex_t frame number에 사용되는 것은 부호 있는 형식이며 API에서 가끔 frame number뿐만 아니라 음수 Error Codes도 반환하는 데 사용됩니다. 특히 32비트 애플리케이션에서는 frame number의 오버플로를 올바르게 처리하도록 주의해야 합니다. FRAMEINDEX_MAX 에 도달하면 이미지 카운팅이 1로 다시 시작됩니다! (64비트 애플리케이션에서는 매우 높은 프레임 속도에서도 이미지 counter의 오버플로는 수십만 년 후에야 발생합니다.)

대조적으로 버퍼 번호는 이미지 데이터가 있는 프레임 버퍼를 나타내며 N개의 버퍼에 대해 다음 범위에 있습니다. [1; N]. 여기서 사용된 예시에서 버퍼 번호는 1 … 4 사이이며, 이는 FB0 … FB3 이에 따라.

The Standard Acquisition Model (ACQ_STANDARD)#
frameindex_t Fg_getLastPicNumberBlockingEx(
    Fg_Struct * fg,
    frameindex_t frame,
    unsigned int dma,
    int timeout,
    dma_mem * mem);
int Fg_getParameterEx(
    Fg_Struct * fg,
    int param,
    void * value,
    unsigned int dma,
    dma_mem * mem,
    frameindex_t frame);

void * Fg_getImagePtrEx(
    Fg_Struct * fg,
    frameindex_t frame,
    unsigned int dma,
    dma_mem * mem);

표준 획득 모델은 다음을 전달하여 선택됩니다. ACQ_STANDARD (으)로 flags 호출 시 Fg_AcquireEx(). 모든 프레임 버퍼는 이미지 데이터를 가져오기 위한 드라이버와 이미지 데이터를 처리하기 위한 애플리케이션 모두에서 항상 접근할 수 있습니다.

Acquisition이 시작되면 드라이버는 첫 번째 프레임 버퍼를 시작으로 이미지 데이터 전송을 위해 프레임 그랩버에 최소 하나의 프레임 버퍼를 대기열에 넣습니다. FB0. 이미지가 컴퓨터 메모리로 완전히 전송되면, 소프트웨어는 전송이 완료되었음을 알리게 되며, 드라이버는 프레임 버퍼를 하나 더 대기열에 추가합니다. 프레임 그래버는 다음 이미지의 데이터 전송을 대기열에 있는 다음 버퍼로 계속 진행하며, 이 예시에서는 FB1.

(대기열에 대기하는 프레임 버퍼의 수는 사용된 프레임 그랩버, 드라이버 버전, Windows 레지스트리 설정 또는 Linux 드라이버 매개변수 등 다양한 요인에 따라 다릅니다. 그러나 표준 Acquisition 모드에서는 대기열 등록이 항상 선형 방식으로 이루어지며 다음으로 시작됩니다.) FB0 마지막 프레임 버퍼가 큐에 추가된 후에 다시 실행됩니다. 큐에 추가된 버퍼의 수는 컴퓨터에서 달성할 수 있는 최대 프레임 속도에 영향을 미칠 수 있지만, 이러한 영향은 초당 약 10,000 프레임 이상일 때만 측정 가능합니다.)

드라이버가 일관된 원형 방식으로 프레임 버퍼를 사용하기 때문에 관계를 사용하여 프레임 번호를 버퍼 번호로 단순하게 변환할 수 있습니다. bufferNumber = 1 + ((frameNumber - 1) % numberOfBuffers). 이 함수는 Fg_getImagePtrEx() 을(를) 사용하면 프레임 번호 또는 버퍼 번호에 대한 프레임 버퍼 포인터를 얻을 수 있습니다.

Standard acquisition model에서 애플리케이션은 이미지 취득이 이미지 처리를 "초과(overrun)"하지 않도록 완전히 책임져야 합니다. 이는 이미지 소스 트리거링이 이미지 처리와 결합하여 애플리케이션에서 제어되는 경우, 버퍼 수가 사용 중인 컴퓨터 시스템의 프레임 속도 및 성능에 신중하게 맞춰진 경우, 또는 이미지를 건너뛸 수 있는 경우에만 보장될 수 있습니다.

이전 이미지가 아직 처리되는 동안 애플리케이션이 단일 이미지만 트리거하는 시나리오에서는 처리 중인 이미지 데이터를 위한 버퍼와 이미지 데이터 전송을 위한 버퍼 등 두 개의 버퍼로 충분합니다. (애플리케이션이 이미지 처리가 완전히 완료된 후에만 트리거가 생성되도록 보장하는 경우 실제로 처리를 위해 하나의 버퍼로 충분합니다. 그러나 이는 Framegrabber API에서 지원되지 않으며, 애플리케이션은 모든 경우에 최소 두 개의 버퍼를 할당해야 합니다.)

애플리케이션 측의 제어 없이 이미지가 지속적으로 생성되는 시나리오에서는 이미지 소스와 드라이버의 버퍼 처리가 모두 프리러닝(free running) 상태인 것으로 간주할 수 있습니다. 다음 예에서는 FB0 및 FB1 유효한 이미지 데이터를 포함합니다. FB0 애플리케이션에 의해 처리되고 있으며, FB1 처리가 대기 중입니다. 드라이버는 최소한 FB2 이미지 데이터가 현재 전송되고 있습니다. 이 상황은 다음과 같은 이유로 여전히 안전합니다. FB3 이미 대기열에 추가되었을 수 있음에도 불구하고 아직 사용 중이 아닙니다.

Memory Buffer Model Safe

함수 호출 Fg_getLastPicNumberBlockingEx() 처리가 완료된 후 다음 frame number에 대해 FB0 완료되면 단일 새 프레임이 반환됩니다(전송된 이미지의 프레임 번호는 FB1) 이 경우 전송 대상이 FB2 그동안 완료되지 않았습니다.

이미지 처리가 이미지 취득보다 느린 경우, 애플리케이션은 다음을 처리하기 위해 진행했을 수 있습니다. FB1. 그러나 다음 예에서는 그 사이에 두 개의 이미지가 더 전송되었으며, FB2 및 FB3, 그리고 드라이버가 다음으로 다시 시작되었습니다: FB0. 이미지 전송이 완료되면 드라이버는 FB1, 따라서 프레임 그라버가 현재 처리 중인 데이터를 덮어쓸 수 있습니다. 이 시나리오는 이미지 소스가 이미지 데이터를 생성하지 않도록 애플리케이션이 보장할 수 있는 경우에만 안전합니다. FB1 여전히 처리 중입니다.

Memory Buffer Model Unsafe

함수 호출 Fg_getLastPicNumberBlockingEx() 처리가 완료된 후 다음 frame number에 대해 FB0 완료되면 두 개의 새로운 프레임이 반환됩니다(전송된 이미지의 프레임 번호는 FB3) 이 경우 전송 대상이 FB0 그동안 완료되지 않았습니다.

다음 예시는 모든 프레임을 처리하기 위해 Writing an Acquisition Loop 섹션에 제시된 acquisition 루프의 구조를 확장합니다.

const int timeoutInSeconds = 10;

frameindex_t nextFrame = 1;
while (true) {
    // get new image
    const frameindex_t newestFrame =
        Fg_getLastPicNumberBlockingEx(fg, nextFrame, dma,
                                      timeoutInSeconds, mem);

    if (newestFrame > 0) {
        for (frameindex_t frame = nextFrame; frame <= newestFrame; ++frame) {
                // get a pointer to the frame buffer for the newest image
                void * ptr =
                    Fg_getImagePtrEx(fg, frame, dma, mem);

            // get the actual number of bytes transferred
            size_t length = 0;
            int result =
                Fg_getParameterEx(fg, FG_TRANSFER_LEN, &length,
                                  dma, mem, frame);

            if ((ptr != nullptr) && (result == FG_OK) && (length > 0)) {
                    // process image data ...
            }
        }

        nextFrame = (newestFrame < FRAMEINDEX_MAX) ? newestFrame + 1 : 1;
    } else {
        // handle error ...
    }
}

애플리케이션이 이미지를 건너뛰고 수신된 가장 최신 프레임만 처리해야 하는 경우, 내부 포 룹을 획득 루프에서 생략하고 대신 다음 페이지만 처리할 수 있습니다. newestFrame.

함수 Fg_getImageEx() 표준 취득 모델과 함께 사용해서는 안 됩니다.

비동기 모드에서 Framegrabber API는 다음을 호출합니다. Fg_getLastPicNumberBlockingEx() 새 이미지를 기다리는 데 사용되며, 플래그가 FG_APC_BATCH_FRAMES 가 설정되었거나, 설정되지 않은 경우 여러 번 수신된 각 이미지마다 한 번씩 호출됩니다. 콜백은 이미지의 프레임 번호를 받습니다.

비동기 모드에서 프레임을 처리하려면, 내부 루프의 내용을 콜백 함수에서 사용할 수 있습니다(ApcCallbackData는 Registering a Callback Function for Asynchronous Mode 섹션에 설명된 구조체임):

int ApcUserCallback(frameindex_t frame, void * data)
{
    auto context = reinterpret_cast<ApcUserCallbackData *>(data);

    if (frame > 0) {
        // get a pointer to the frame buffer for the newest image
        void * ptr =
            Fg_getImagePtrEx(context->fg, frame, context->dma, context->mem);

        // get the actual number of bytes transferred
        size_t length = 0;
        int result =
            Fg_getParameterEx(context->fg, FG_TRANSFER_LEN, &length,
                              context->dma, context->mem, frame);

        if ((ptr != nullptr) && (result == FG_OK) && (length > 0)) {
            // process image data ...
        }
    } else {
        // handle error ...
    }

    return 0;
}

이러한 방식으로 콜백 함수는 다음 경우에 가장 최신 이미지마저 처리하는 용도와 FG_APC_BATCH_FRAMES 전달되었습니다. flags (으)로 Fg_registerApcHandlerEx(), 모든 이미지를 처리하는 용도로 모두 사용할 수 있습니다. 콜백 함수는 다음 경우에 각 새 이미지마다 한 번씩 여러 번 호출됩니다. FG_APC_BATCH_FRAMES 전달되지 않았습니다.

The Blocking Acquisition Model (ACQ_BLOCK)#
frameindex_t Fg_getImageEx(
    Fg_Struct * fg,
    int strategy,
    frameindex_t frame,
    unsigned int dma,
    unsigned int timeout,
    dma_mem * mem);
int Fg_getParameterEx(
    Fg_Struct * fg,
    int param,
    void * value,
    unsigned int dma,
    dma_mem * mem,
    frameindex_t buffer);

void * Fg_getImagePtrEx(
    Fg_Struct * fg,
    frameindex_t buffer,
    unsigned int dma,
    dma_mem * mem);

frameindex_t Fg_getStatusEx(
    Fg_Struct * fg,
    int status,
    frameindex_t buffer,
    unsigned int dma,
    dma_mem * mem);
int Fg_setStatusEx(
    Fg_Struct * fg,
    int status,
    frameindex_t buffer,
    unsigned int dma,
    dma_mem * mem);

정보

블로킹 획득 모델에서 비동기 모드를 사용할 때의 동작 ACQ_BLOCK Framegrabber API 버전 5.9에서 변경되었습니다.

블로킹 획득 모델은 다음을 전달하여 선택됩니다. ACQ_BLOCK (으)로 flags 호출 시 Fg_AcquireEx(). 각 프레임 버퍼는 이미지 데이터 취득을 위해 드라이버에서 독점적으로 액세스하거나, 애플리케이션이 이미지 데이터를 처리하도록 대기열에 등록되거나 차단됩니다. 프레임 버퍼가 차단되어 있는 한 프레임 버퍼를 사용하는 것은 항상 안전하지만, 이미지 데이터 전송에 사용할 수 있는 차단 해제된 버퍼가 더 이상 없는 상황이 드라이버에서 발생하면 이미지가 손실될 수 있습니다.

Acquisition이 시작되면 드라이버는 첫 번째 프레임 버퍼를 시작으로 이미지 데이터 전송을 위해 프레임 그랩버에 최소 하나의 프레임 버퍼를 대기열에 넣습니다. FB0. 이미지가 컴퓨터 Memory로 완전히 전송되면, 소프트웨어에 전송 완료가 통지되고, 프레임 버퍼는 애플리케이션용으로 대기열에 추가되며, 애플리케이션이 명시적이거나 암시적으로 차단을 해제할 때까지 드라이버는 이를 사용하지 않습니다. 차 해제된 하나 이상의 프레임 버퍼를 사용할 수 있는 한, 드라이버는 프레임 grabber에 하나 이상의 프레임 버퍼를 더 대기열에 추가합니다. 더 이상 차단 해제된 프레임 버퍼를 사용할 수 없는 경우, 다음이라는 특수 프레임 버퍼가 dummy buffer (이)가 프레임 grabber의 대기열에 추가되어 이미지 acquisition이 항상 실행되도록 유지합니다. 프레임 grabber는 다음 이미지에 대한 데이터 전송을 대기열의 다음 버퍼로 계속 진행하며, 본 예시에서는 다음과 같습니다. FB1.

(하위 섹션 The Standard Acquisition Model에서 언급했듯이, 프레임 grabber에 대기열로 추가된 프레임 버퍼의 수는 다양한 요인에 따라 달라집니다.)

더미 프레임 버퍼는 무한히 큰 것으로 간주할 수 있으며 임의 크기의 데이터를 흡수할 수 있지만 이미지 처리에 의미 있는 방식은 아닙니다. 이로 인해 더미 버퍼는 애플리케이션에서 액세스할 수 없으며 더미 버퍼로 전송된 모든 이미지는 손실됩니다. 프레임이 전송될 때마다 다음 버퍼의 큐 추가가 자동으로 이루어지므로, 드라이버가 큐에 추가할 수 있는 차단 해제된 프레임 버퍼가 없는 경우 적어도 하나의 이미지가 자동으로 손실됨을 의미합니다. 이는 데이터 소스가 중지되었다가 프레임 버퍼를 다시 사용할 수 있게 된 후에야 다시 시작되는 경우에도 마찬가지입니다!

동기 모드에서 함수는 Fg_getImageEx() 새로 취득한 이미지에 대해 하나의 프레임 버퍼를 요청하고 차단하도록 호출해야 합니다. 이 함수는 차단된 프레임 버퍼의 버퍼 번호를 반환합니다. 차단 취득 모델과 관련된 전략은 다음과 같습니다.

Strategy 설명
SEL_NEXT_IMAGE 다음 프레임의 버퍼 번호를 반환합니다.
이 strategy는 전송된 순서대로 각 단일 프레임을 하나씩 처리하는 데 사용됩니다.
SEL_ACT_IMAGE 가장 최근 프레임의 버퍼 번호를 반환합니다.
이 strategy는 이미지 처리가 Acquisition Frame Rate보다 느릴 때 프레임을 건너뛸 수 있도록 하는 데 사용됩니다.

위의 목록은 완전하지 않으며 블로킹 획득 모델과 관련된 전략만 포함하고 있습니다.

경우 SEL_NEXT_IMAGE 가 사용되면 다음 프레임 버퍼만 차단되며, 다른 모든 버퍼는 나중에 애플리케이션에서 요청할 수 있도록 큐에 유지됩니다. 만약 SEL_ACT_IMAGE 사용되는 경우 최신 프레임 버퍼만 차단되고, 애플리케이션용으로 대기 중인 다른 모든 프레임 버퍼는 대기열에서 제거되며 암시적으로 차단이 해제됩니다.

함수를 호출할 때 Fg_getImageEx() 이 모델을 사용하는 경우 항상 0을 전달해야 합니다. frame. 이 함수는 특정 프레임 번호를 기다리거나 프레임 번호를 버퍼 번호로 변환하는 데 사용할 수 없습니다. 프레임 버퍼의 프레임 번호를 얻으려면 함수를 사용합니다. Fg_getParameterEx() 전달하여 호출할 수 있습니다. FG_IMAGE_NUMBER 매개변수 내 param, 형식의 변수에 대한 포인터 frameindex_t 프레임 번호 및 매개변수의 버퍼 번호에 대해 buffer.

함수 Fg_getStatusEx() 차단 취득 모델과 관련된 다음 상태 정보를 요청하기 위해 호출할 수 있습니다.

Status 설명
NUMBER_OF_LOST_IMAGES 손실된 프레임 수
NUMBER_OF_BLOCKED_IMAGES 현재 차단된 프레임 수
NUMBER_OF_IMAGES_IN_PROGRESS 다음을 통해 사용할 수 있는 프레임 수 Fg_getImageEx()
BUFFER_STATUS 0: 프레임 버퍼가 차단되지 않음
1: 프레임 버퍼가 차단됨

함수 Fg_setStatusEx() 이전에 호출하여 요청하고 차단한 프레임 버퍼의 차단을 해제하기 위해 호출할 수 있습니다. Fg_getImageEx():

Status 설명
FG_UNBLOCK 단일 프레임 버퍼 차단 해제
FG_UNBLOCK_ALL 현재 차단된 모든 버퍼의 차단 해제

FG_UNBLOCK_ALL 또한 아직 요청 및 차단되지 않은 채 애플리케이션용으로 대기 중인 모든 버퍼도 제거합니다.

함수를 사용할 때 Fg_AcquireEx() 캡처할 이미지 수를 지정하기 위해, 손실된 이미지뿐만 아니라 성공적으로 전달된 이미지도 고려됩니다. 이로 인해 예상치 못한 결과가 발생할 수 있습니다. FG_TIMEOUT_ERR 또는 FG_TRANSFER_NOT_ACTIVE 호출 시 결과 Fg_getImageEx() 그리고 획득 루프에서 전달된 이미지만 카운트합니다.

이전 이미지가 계속 처리되는 동안 애플리케이션이 단일 이미지 하나만 트리거하는 시나리오에서는 처리 중인 이미지 데이터용과 이미지 데이터 전송용으로 버퍼 2개가 충분합니다. (버퍼 잠금이 발생하므로 애플리케이션이 이미지가 완전히 처리된 후에만 트리거가 생성되도록 하더라도 모든 경우에 최소 2개의 버퍼가 필요합니다.)

애플리케이션 측에서 제어 없이 이미지가 지속적으로 생성되는 상황에서는, 이미지 소스가 자유롭게 실행되는 것으로 간주할 수 있습니다. 그러나 드라이버는 차단되지 않은 버퍼가 남아 있는 경우에만 애플리케이션에 이미지를 전달할 수 있습니다. 다음 예시에서, FB0 및 FB1 유효한 이미지 데이터를 포함합니다. FB0 애플리케이션에 의해 처리되고 있으며, FB1 처리가 대기 중입니다. 드라이버는 최소한 FB2 이미지 데이터가 현재 전송되고 있습니다. 이 상황은 다음과 같은 이유로 여전히 안전합니다. FB3 이미 대기열에 추가되었을 수 있음에도 불구하고 아직 사용 중이 아닙니다.

Memory Buffer Model Safe

이미지 처리가 이미지 취득보다 느린 경우 애플리케이션이 처리를 완료했을 수 있습니다. FB0, 차단을 해제하고 진행하여 처리했습니다. FB1. 그러나 다음 예에서는 그 사이에 두 개의 이미지가 더 전송되었으며, FB2 및 FB3, 그리고 드라이버가 다음으로 다시 시작되었습니다: FB0. 이미지 전송이 완료되었을 때, 애플리케이션의 처리가 완료되지 않은 경우 FB1 그리고 이를 잠금 해제하면 드라이버에 큐에 넣을 수 있는 빈 버퍼가 더 이상 남지 않게 됩니다. 더미 버퍼가 큐에 들어가고 취득 과정에서 최소한 하나의 이미지는 손실되지만, 아직 차단 해제되지 않은 프레임 버퍼의 데이터 무결성은 유지됩니다.

Memory Buffer Model Unsafe

다음 예시는 모든 프레임을 처리하기 위해 Writing an Acquisition Loop 섹션에 제시된 acquisition 루프의 구조를 확장합니다.

const int timeoutInSeconds = 10;
while (true) {
    // get new image
    frameindex_t buffer =
        Fg_getImageEx(fg, SEL_NEXT_IMAGE, 0, dma, timeoutInSeconds, mem);

    if (buffer > 0)
        // get the frame number (if needed)
        uint64_t frame = 0;
        Fg_getParameterEx(fg, FG_IMAGE_NUMBER, &frame, dma, mem, buffer);

        // get a pointer to the frame buffer for the newest image
        void * ptr = Fg_getImagePtrEx(fg, buffer, dma, mem);

        // get the actual number of bytes transferred
        size_t length = 0;
        int result =
            Fg_getParameterEx(fg, FG_TRANSFER_LEN, &length, dma, mem, buffer);

        if ((ptr != nullptr) && (result == FG_OK) && (length > 0)) {
            // process image data ...
        }

        // unblock frame buffer
        Fg_setStatusEx(fg, FG_UNBLOCK, buffer, dma, mem);
    } else {
        // handle error ...
    }
}

함수 Fg_getLastPicNumberBlockingEx() 차단 획득 모델과 함께 사용해서는 안 됩니다.

비동기 모드에서 Framegrabber API는 다음을 호출합니다. Fg_getImageEx() 사용 SEL_ACT_IMAGE 플래그가 있는 경우 FG_APC_BATCH_FRAMES 가 설정되었거나 다음을 사용하는 경우 SEL_NEXT_IMAGE 설정되지 않은 경우 콜백 함수는 이미지의 버퍼 번호를 받게 됩니다.c

비동기 모드에서 프레ーム을 처리하기 위해, 콜백 함수에서 if 절을 사용할 수 있습니다(ApcUserCallbackData는 비동기 모드를 위한 콜백 함수 등록 섹션에 설명된 구조체입니다):

int ApcUserCallback(frameindex_t buffer, void * data)
{
    auto context = reinterpret_cast<ApcUserCallbackData *>(data);

    if (buffer > 0) {
        // get the frame number (if needed)
        uint64_t frame = 0;
        Fg_getParameterEx(fg, FG_IMAGE_NUMBER, &frame, dma, mem, buffer);

        // get a pointer to the frame buffer for the newest image
        void * ptr =
            Fg_getImagePtrEx(context->fg, buffer, context->dma, context->mem);

        // get the actual number of bytes transferred
        size_t length = 0;
        int result =
            Fg_getParameterEx(context->fg, FG_TRANSFER_LEN, &length,
                              context->dma, context->mem, buffer);

        if ((ptr != nullptr) && (result == FG_OK) && (length > 0)) {
            // process image data ...
        }

        // unblock frame buffer
        Fg_setStatusEx(fg, FG_UNBLOCK, buffer, dma, mem);
    } else {
        // handle error ...
    }

    return 0;
}

이러한 방식으로 콜백 함수는 다음 경우에 가장 최신 이미지마저 처리하는 용도와 FG_APC_BATCH_FRAMES 전달되었습니다. flags (으)로 Fg_registerApcHandlerEx(), 모든 이미지를 처리하는 용도로 모두 사용할 수 있습니다. 콜백 함수는 다음 경우에 각 새 이미지마다 한 번씩 여러 번 호출됩니다. FG_APC_BATCH_FRAMES 전달되지 않았습니다.

선택적 Acquisition 모델 ACQ_SELECT#
frameindex_t Fg_getLastPicNumberBlockingEx(
    Fg_Struct * fg,
    frameindex_t frame,
    unsigned int dma,
    int timeout,
    dma_mem * mem);
int Fg_getParameterEx(
    Fg_Struct * fg,
    int param,
    void * value,
    unsigned int dma,
    dma_mem * mem,
    frameindex_t frame);

void * Fg_getImagePtrEx(
    Fg_Struct * fg,
    frameindex_t buffer,
    unsigned int dma,
    dma_mem * mem);
int Fg_setStatusEx(
    Fg_Struct * fg,
    int status,
    frameindex_t buffer,
    unsigned int dma,
    dma_mem * mem);

정보

선택적 취득 모델 ACQ_SELECT Framegrabber SDK 버전 5.9에 추가되었습니다.

선택적 취득 모델을 선택하려면 다음을 전달합니다. ACQ_SELECT (으)로 flags 호출 시 Fg_AcquireEx(). 애플리케이션은 드라이버의 프레임 버퍼 사용을 완전히 제어할 수 있습니다.

프레임 버퍼는 프레임 그래버에서 큐에 넣기 위해 명시적으로 선택되어야 하며, 드라이버는 선택된 정확한 순서대로 프레임 버퍼를 큐에 넣습니다. 취득이 시작되면 드라이버는 선택된 첫 번째 프레임 버퍼를 시작으로 프레임 버퍼가 하나 이상 선택된 경우에만 이미지 데이터 전송을 위해 프레임 그래버의 프레임 버퍼를 큐에 넣습니다. 컴퓨터 Memory로 이미지 전송이 완전히 완료되면 소프트웨어에 전송 완료가 통지되며, 해당 프레임 버퍼는 더 이상 선택된 것으로 간주되지 않고 명시적으로 다시 선택될 때까지 드라이버에서 사용되지 않습니다. 드라이버는 사용 가능한 경우 하나 이상의 프레임 버퍼를 더 큐에 넣습니다. 사용 가능한 프레임 버퍼가 없으면 큐에 들어가는 프레임 버퍼가 없습니다. 프레임 그래버는 큐의 다음 버퍼로 다음 이미지에 대한 데이터 전송을 계속합니다. 프레임 그래버의 큐가 비어 있게 되면 내부 버퍼 오버플로우가 발생하여 이미지가 손실될 수 있습니다.

(하위 섹션 The Standard Acquisition Model에서 언급했듯이, 프레임 grabber에 대기열로 추가된 프레임 버퍼의 수는 다양한 요인에 따라 달라집니다.)

애플리케이션이 프레임 버퍼 사용을 완전히 제어하므로 버퍼 번호 추적 역시 애플리케이션의 책임입니다. 프레임 버퍼가 항상 동일한 순서로 선택되지 않는 한, 프레임 번호를 버퍼 번호로 변환하는 단순한 방법은 없습니다. 또한 변환을 수행하는 API 함수도 없습니다.

함수 Fg_setStatusEx() 을 사용하여 프레임 버퍼를 선택하도록 호출할 수 있습니다. FG_SELECT_BUFFER 및 버퍼 번호 전달.

간단히 설명하기 위해 다음 예시에서는 취득을 시작한 후 4개의 버퍼가 모두 FB0 … FB3 자연스러운 순서로 선택됩니다. 또한 이미지 전송이 완료된 후 처리되고 버퍼가 순서대로 다시 선택됩니다. 이렇게 하면 버퍼 시퀀스가 항상 동일하게 유지되며, 다음 관계를 사용하여 프레임 번호를 버퍼 번호로 단순하게 변환할 수 있습니다. bufferNumber = 1 + ((frameNumber - 1) % numberOfBuffers).

애플리케이션 측의 제어 없이 이미지가 지속적으로 생성되는 시나리오에서는 이미지 소스가 프리런(free-running) 상태인 것으로 간주할 수 있습니다. 그러나 드라이버는 선택된 버퍼를 계속 사용할 수 있는 경우에만 애플리케이션에 이미지를 전달할 수 있습니다. 다음 예시에서, FB0 및 FB1 유효한 이미지 데이터를 포함하고 있으며 선택되지 않았습니다. FB0 애플리케이션에 의해 처리되고 있으며, FB1 처리가 대기 중입니다. 드라이버는 최소한 FB2 이미지 데이터가 현재 전송되고 있습니다. 이 상황은 다음과 같은 이유로 여전히 안전합니다. FB3 이미 대기열에 추가되었을 수 있음에도 불구하고 아직 사용 중이 아닙니다.

Memory Buffer Model Safe

함수 호출 Fg_getLastPicNumberBlockingEx() 처리가 완료된 후 다음 frame number에 대해 FB0 완료되면 단일 새 프레임이 반환됩니다(전송된 이미지의 프레임 번호는 FB1) 이 경우 전송 대상이 FB2 그동안 완료되지 않았습니다.

이미지 처리가 이미지 취득보다 느린 경우 애플리케이션이 처리를 완료했을 수 있습니다. FB0, 이를 선택하고 다음 처리를 진행했습니다 FB1. 그러나 다음 예에서는 그 사이에 두 개의 이미지가 더 전송되었으며, FB2 및 FB3, 그리고 드라이버가 다음으로 다시 시작되었습니다: FB0. 이미지 전송이 완료되었을 때, 애플리케이션의 처리가 완료되지 않은 경우 FB1 그리고 이를 선택하면, 드라이버에는 큐에 넣을 수 있는 무료 버퍼가 더 이상 남지 않게 됩니다. 추가 이미지가 도착하지 않는 한, 이 상황은 다음과 같은 상황에서 발생할 수 있는 암시적 이미지 손실을 유발하지 않습니다. ACQ_BLOCK. 하지만 다른 이미지가 수신되는 즉시 프레임 그래버의 내부 메모리 버퍼에서 오버플로우 상태가 발생하여 데이터가 손실될 수 있습니다.

Memory Buffer Model Unsafe

다음 예시는 모든 프레임을 처리하기 위해 Writing an Acquisition Loop 섹션에 제시된 acquisition 루프의 구조를 확장합니다.

const frameindex_t numberOfBuffers = 4;
const int timeoutInSeconds = 10;

frameindex_t nextFrame = 1;
while (true) {
    // get new image
    const frameindex_t newestFrame =
        Fg_getLastPicNumberBlockingEx(fg, nextFrame, dma,
                                      timeoutInSeconds, mem);

    if (newestFrame > 0) {
        for (frameindex_t frame = nextFrame; frame <= newestFrame; ++frame) {
            // get the buffer number
            frameindex_t buffer = 1 + ((frame - 1) % numberOfBuffers);

            // get a pointer to the frame buffer for the newest image
            void * ptr = Fg_getImagePtrEx(fg, buffer, dma, mem);

            // get the actual number of bytes transferred
            size_t length = 0;
            int result =
                Fg_getParameterEx(fg, FG_TRANSFER_LEN, &length,
                                  dma, mem, buffer);

            if ((ptr != nullptr) && (result == FG_OK) && (length > 0)) {
                // process image data ...
            }

            // select frame buffer
            Fg_setStatusEx(fg, FG_SELECT_BUFFER, buffer, dma, mem);
        }

        nextFrame = (newestFrame < FRAMEINDEX_MAX) ? newestFrame + 1 : 1;
    } else {
        // handle error ...
    }
}

애플리케이션이 이미지를 건너뛸 수 있고 수신된 최신 프레임만 처리해야 하는 경우, Fg_setStatusEx() 와(과) 함께 사용해야 합니다. FG_SELECT_BUFFER 건너뛴 버퍼를 선택합니다. 그렇지 않으면 애플리케이션에 사용되지 않는 버퍼가 남게 됩니다.

함수 Fg_getImageEx() 선택적 취득 모델과 함께 사용해서는 안 됩니다.

비동기 모드에서 Framegrabber API는 다음을 호출합니다. Fg_getLastPicNumberBlockingEx() 새 이미지를 기다리는 데 사용되며, 플래그가 FG_APC_BATCH_FRAMES 가 설정되었거나, 설정되지 않은 경우 여러 번 수신된 각 이미지마다 한 번씩 호출됩니다. 콜백은 이미지의 프레임 번호를 받습니다.

비동기 모드에서 프레임을 처리하기 위해, 콜백 함수에서 내부 루프의 내용을 사용할 수 있습니다(ApcUserCallbackData는 비동기 모드를 위한 콜백 함수 등록 섹션에 설명된 구조체입니다):

int ApcUserCallback(frameindex_t frame, void * data)
{
    auto context = reinterpret_cast<ApcUserCallbackData *>(data);

    if (frame > 0) {
        // get the buffer number
        frameindex_t buffer = 1 + ((frame - 1) % numberOfBuffers);

        // get a pointer to the frame buffer for the newest image
        void * ptr = Fg_getImagePtrEx(fg, buffer, dma, mem);

        // get the actual number of bytes transferred
        size_t length = 0;
        int result =
            Fg_getParameterEx(fg, FG_TRANSFER_LEN, &length, dma, mem, buffer);

        if ((ptr != nullptr) && (result == FG_OK) && (length > 0)) {
            // process image data ...
        }

        // select frame buffer
        Fg_setStatusEx(fg, FG_SELECT_BUFFER, buffer, dma, mem);
    } else {
        // handle error ...
    }

    return 0;
}

이러한 방식으로 콜백 함수는 다음 경우에 가장 최신 이미지마저 처리하는 용도와 FG_APC_BATCH_FRAMES 전달되었습니다. flags (으)로 Fg_registerApcHandlerEx(), 모든 이미지를 처리하는 용도로 모두 사용할 수 있습니다. 콜백 함수는 다음 경우에 각 새 이미지마다 한 번씩 여러 번 호출됩니다. FG_APC_BATCH_FRAMES 전달되지 않았습니다.

프레임 그래버로 데이터 전송#

제한 사항

이 섹션에서는 VisualApplets operator을 사용하는 애플리케이션을 위한 새로운 API에 대해 설명합니다. DmaFromPC. 이 API에는 다음과 같은 제한 사항이 있습니다:

  • 이는 예비 기능 미리 보기입니다. 즉, 향후 Framegrabber SDK 버전에서 함수 이름과 기능이 변경될 수 있습니다.
  • VisualApplets operator을 포함하는 앱릿에서만 작동합니다. DmaFromPC. 일반 DMA 채널에 API를 사용하지 마십시오. DmaToPC 또는 Framegrabbers SDK와 함께 제공되는 Advanced Acquisition Applets에서 작동합니다. operator DmaFromPC VisualApplets 버전 3.4.0 이상에서 사용할 수 있습니다.
  • 현재 Windows용으로만 구현되어 있습니다.

VisualApplets 오퍼레이터 사용 DmaFromPC, PC에서 프레임 그래버로 데이터를 전송할 수 있습니다. 응용 분야에는 이미지 데이터 공동 처리 또는 프레임 그래버에서의 복잡한 이미지 처리를 위한 추가 파라미터 제공 등이 포함되지만 이에 국한되지 않습니다.

Memory 할당#

데이터를 전송할 버퍼는 고급 Memory 관리에 문서화된 함수를 사용하여 할당해야 합니다. 예:

const size_t bufferSize = 1024 * 1024;
const size_t numBuffers = 16;
const size_t totalSize = bufferSize * numBuffers;

dma_mem * mem = Fg_AllocMemEx(fg, totalSize, numBuffers);
if (mem != nullptr) {
    // use memory, send buffers ...

    Fg_FreeMem(fg, mem);
}

또는 유연한 Memory 관리에 문서화된 함수를 사용할 수 있습니다. 예:

dma_mem * mem = Fg_AllocMemHead(fg, totalSize, numBuffers);
for (int i = 0; i < numBuffers; i++) {
    auto buffer = new uint8_t[bufferSize];
    Fg_AddMem(fg, buffer, bufferSize, i, mem);
}

버퍼의 크기는 모두 동일하지만, 각 단일 전송에 대한 바이트 수는 개별적으로 지정됩니다. 데이터 전송 크기는 operator의 Parallelism의 배수여야 합니다. DmaFromPc(32이며 상한선은 버퍼의 크기입니다).

데이터 전송 시작#

 int Fg_startBufferQueue(
    Fg_Struct * fg,
    uint32_t dma,
    dma_mem * mem);

int Fg_stopBufferQueue(
    Fg_Struct * fg,
    uint32_t dma,
    int32_t flags);

프레임 그래버로의 데이터 전송을 시작하려면 다음 함수를 호출합니다. Fg_startBufferQueue(). 이 호출은 DMA 채널을 연결합니다. dma memory handle로 mem 따라서 데이터 전송을 위해 할당된 Memory를 사용하게 됩니다.

파라미터는 dma 함수에 Fg_startBufferQueue() VisualApplets operator를 사용하여 PC로 이미지를 전송하기 위한 일반 DMA 채널 수에 의해 결정됩니다. DmaToPC VisualApplets 디자인에 존재합니다. VisualApplets 오퍼레이터의 DMA 채널은 DmaFromPC 항상 마지막 DMA 채널입니다.

모든 데이터 전송이 완료된 후, 다음 함수 호출이 Fg_stopBufferQueue() 버퍼 큐를 중지하고 DMA 채널과 사용된 Memory 핸들 간의 연결을 해제합니다.

데이터 전송을 위한 버퍼 대기열 등록#

int Fg_queueBuffer(
    Fg_Struct * fg,
    frameindex_t buffer,
    uint64_t numBytesToTransfer,
    uint32_t dma,
    dma_mem * mem);

프레임 그래버로 전송할 데이터가 버퍼에 기록되고 버퍼가 전송 준비가 되면, 다음 함수를 호출하여 버퍼를 버퍼 대기열에 넣을 수 있습니다. Fg_queueBuffer(). 큐에 넣는 각 버퍼에 대해 전송할 바이트 수를 지정해야 합니다.

버퍼 대기열에는 최대 16개의 버퍼를 넣을 수 있습니다. 대기열의 다음 버퍼는 드라이버에 의해 프레임 그래버로 자동 전송됩니다. 이를 통해 필요한 경우 프레임 그래버로의 지속적인 데이터 스트림을 보장할 수 있습니다.

파라미터는 mem 버퍼 큐가 시작되기 전에 버퍼가 큐에 추가되는 경우에만 필요합니다. 후 Fg_startBufferQueue() 이(가) 호출되면 파라미터는 mem 선택 사항이며 NULL.

버퍼 전송 완료 대기#

int Fg_waitForBuffers(
    Fg_Struct * fg,
    uint32_t dma,
    uint64_t timeout,
    void * /* reserved */,
    size_t /* reserved */);

함수 Fg_waitForBuffers() 파라미터에 지정된 초 내에 적어도 하나의 버퍼가 완전히 전송될 때까지 대기합니다. timeout 파라미터에 지정된 특정 DMA 채널에서 dma(으)로 설정할 수 있습니다. 이 함수는 성공 시 완전히 전송된 버퍼 수를 반환하고, 실패 시 음수 오류 코드를 반환합니다.

다음 함수를 사용하여 대기열에 추가된 버퍼만 재사용할 수 있습니다. Fg_queueBuffer() 버퍼가 완전히 전송되면 새 데이터로 채웁니다.

VisualApplets 오퍼레이터의 데이터 전송 모델은 DmaFromPC 은 다음와 매우 유사합니다 선택적 Acquisition 모델. 즉, 애플리케이션이 버퍼 사용을 완벽하게 제어하므로 버퍼 번호를 추적하는 책임도 애플리케이션에 있습니다. 버퍼가 항상 동일한 순서로 선택되지 않는 한, 전송 Counter를 버퍼 번호로 변환하는 단순한 방법은 없습니다. 또한 변환을 수행하는 API 함수도 없습니다.

Applet 이벤트#

Framegrabber SDK 설치에 포함된 애플릿은 프레임 그래버의 이미지 취득 또는 처리와 관련된 다양한 이벤트를 애플리케이션에 알릴 수 있습니다. 이러한 이벤트의 예로는 카메라에서 이미지의 첫 번째 또는 마지막 픽셀이 수신될 때마다 생성되는 프레임 시작 이벤트나 프레임 종료 이벤트, 또는 트리거 입력 신호 에지가 감지될 때마다 생성되는 트리거 입력 상승 이벤트 또는 트리거 입력 하강 이벤트가 있습니다. VisualApplets 사용자는 애플리케이션에 필요한 이벤트를 생성하기 위해 디자인 내에서 이벤트 오퍼레이터를 사용할 수 있습니다.

각 이벤트 소스는 고유한 이름을 가지며 이벤트 마스크라고 하는 부호 없는 64비트 정수의 단일 비트로 식별됩니다. 이런 방식으로 이벤트 마스크에서 여러 비트를 설정하여 여러 이벤트 소스를 그룹화할 수 있습니다(예: binary or operator 사용). | 여러 이벤트 소스에 대한 여러 이벤트 마스크에 사용할 수 있습니다. 그러나 이는 또한 모든 애플릿이 최대 64개의 이벤트 소스만 지원할 수 있음을 의미합니다.

이벤트는 동기 또는 비동기 모드로 전달될 수 있습니다. 동기 모드에서는 애플리케이션이 이벤트 루프를 제공해야 합니다. 비동기 모드에서는 하나 이상의 이벤트가 발생할 때마다 호출될 콜백 함수를 등록할 수 있습니다. 리소스 충돌을 일으킬 수 있으므로 두 가지 접근 방식을 애플리케이션에서 혼용해서는 안 됩니다.

이벤트 소스는 컴퓨터 시스템에 높은 인터럽트 부하를 발생시킬 수 있으므로 각 이벤트 소스는 명시적으로 활성화되어야 하며 필요할 때만 활성화해야 합니다.

이벤트가 발생할 때마다 이벤트 소스의 인터럽트가 수신된 시간이 기록됩니다. 타임스탬프 외에도 일부 이벤트 소스는 이벤트 페이로드라고 하는 각 이벤트와 함께 추가 데이터를 생성할 수 있습니다. 페이로드가 있는 이벤트는 둘 이상의 이벤트 소스에 대해 여러 비트를 설정하여 함께 그룹화할 수 없습니다. 사용하는 애플릿의 이벤트 소스가 추가 데이터를 생성하는지 여부와 해당 데이터를 해석하는 방법에 대한 자세한 내용은 해당 애플릿의 설명서를 참조하십시오.

이벤트 정보#

uint64_t Fg_getEventMask(
    Fg_Struct * fg,
    const char * name);

int Fg_getEventPayload(
    Fg_Struct * fg,
    uint64_t mask);

int Fg_getEventCount(
    Fg_Struct * fg);

const char * Fg_getEventName(
    Fg_Struct * fg,
    uint64_t mask);

이벤트 소스의 이름을 알고 있는 경우 함수를 호출하여 해당 비트를 요청할 수 있습니다. Fg_getEventMask(). 이벤트를 인식할 수 없는 경우, 이 함수는 0을 반환합니다.

임의의 이벤트에 대한 페이로드 크기는 다음 함수를 호출하여 요청할 수 있습니다. Fg_getEventPayload(). 이벤트 마스크가 단일 유효 이벤트 소스에 해당하는 경우 이 함수는 0 이상 값을 반환하며, 그렇지 않은 경우 음수 오류 코드를 반환합니다.

모든 이벤트 소스를 반복하려면 다음 함수를 Fg_getEventCount() 호출하여 앱릿이 지원하는 이벤트 소스 수를 요청할 수 있으며, 다음 함수를 Fg_getEventName() 사용하여 이벤트 소스의 이름을 가져올 수 있습니다. 이는 다음 예시에 나와 있습니다.

int numEvents = Fg_getEventCount(fg);
for (int event = 0; event < numEvents; ++event) {
    // get the event mask for each event
    const uint64_t eventMask = (1 << event);

    const char * eventName = Fg_getEventName(fg, eventMask);
    if (eventName != nullptr) {
        std::cout << "Event " << event << " is " << eventName << std::endl;
    }
}

비동기 이벤트 처리를 위한 콜백 함수 등록#

typedef int (* Fg_EventFunc_t)(
    uint64_t events,
    void * data,
    const struct fg_event_info * info);

int Fg_registerEventCallback(
    Fg_Struct * fg,
    uint64_t mask,
    Fg_EventFunc_t handler,
    void * data,
    unsigned int flags,
    struct fg_event_info * info);

int Fg_unregisterEventCallback(
    Fg_Struct * fg,
    uint64_t mask);

정보

Framegrabber SDK 버전 5.9에서 다음 타입은 struct fg_event_data 제거되었으며 다음 함수가 Fg_unregisterEventCallback() 이(가) 추가되었습니다. 섹션 참조 Plain C에서 비동기 이벤트 처리를 위한 콜백 함수 등록 해제 을(를) 참조하십시오.

사용 Fg_registerEventCallback(), 다음 유형의 함수 Fg_EventFunc_t 이벤트 소스 그룹에서 하나 이상의 이벤트가 수신될 때 콜백되도록 등록할 수 있습니다. 이 함수는 지정된 frame grabber와 이벤트 마스크에 대해 등록되며, 호출 시 세 개의 파라미터가 전달됩니다. 콜백 함수의 첫 번째 파라미터는 이벤트가 수신된 모든 이벤트 소스의 이벤트 마스크입니다. 두 번째 파라미터는 다음 호출 시 Fg_registerEventCallback() 그리고 컨텍스트 구조체나 클래스에 대한 포인터로 사용할 수 있습니다. 예: this 이미지 처리를 구현하는 클래스 인스턴스의 포인터가 제공된 포인터입니다. 세 번째 파라미터는 다음 항목에 대한 포인터이며, struct fg_event_info 애플리케이션에서 할당하여 다음 호출 시 전달해야 하며 Fg_registerEventCallback() , 이벤트에 대한 정보를 저장하는 데 사용됩니다.

특정 frame grabber에서 동일한 이벤트 그룹에 대해 하나의 콜백 함수만 등록할 수 있습니다.

콜백 함수는 Framegrabber API가 제공하는 이벤트 루프에서 호출됩니다. 이는 콜백 함수가 이벤트 루프의 스레드 컨텍스트에서 호출됨을 의미합니다. 또한 콜백 함수가 반환될 때까지 걸리는 시간이 이벤트 루프의 일반 관리 오버헤드에 추가되며, 이 시간 동안 여러 이벤트가 수신되었을 수 있음을 의미합니다. 해당 시간 동안 이벤트가 수신된 경우, 콜백 함수는 반환 직후 즉시 다시 호출됩니다.

다음 파라미터를 통해 flags 호출 시 Fg_registerEventCallback(), 애플리케이션은 콜백 함수가 호출될 때마다 단일 이벤트만 전달될지 아니면 대기 중인 모든 이벤트가 그룹화될지 선택할 수 있습니다. 다음 값을 전달할 때의 기본 동작은 FG_EVENT_DEFAULT_FLAGS 파라미터에 flags , 콜백 함수가 호출될 때마다 하나의벤트를 전달하는 것입니다. 다음 값을 전달하면 FG_EVENT_BATCHED 대기 중인 모든 이벤트가 함께 그룹화됩니다.

콜백 함수가 더 이상 필요하지 않게 되면 다음을 호출하여 등록을 해제할 수 있습니다. Fg_unregisterEventCallback().

다음 예제는 이미지 수집 처리에 필요한 정보를 담고 있는 간단한 구조체를 사용하여 콜백 함수를 등록하는 방법을 보여줍니다.

struct EventUserCallbackData
{
    Fg_Struct * fg;
    fg_event_info info;
    uint64_t mask;
};

int EventUserCallback(uint64_t events, void * data,
                      const struct fg_event_info * info)
{
    auto context = reinterpret_cast<EventUserCallbackData *>(data);

    // process events

    return 0;
}

void SetupEventUserCallback(EventUserCallbackData * context)
{
    // register callback function
    int result = Fg_registerEventCallback(
        context->fg, context->mask, &EventUserCallback, context,
        FG_EVENT_DEFAULT_FLAGS, &context->info);
    if (result != FG_OK) {
        throw std::runtime_error("Failed to register callback function");
    }
}

컨텍스트 구조의 할당 및 관리는 예제에 표시되지 않습니다. 포인터는 콜백 함수가 등록되어 있는 동안 유효해야 합니다. 한 가지 해결책은 C++ 클래스 내에서 모든 것을 함께 유지하는 것입니다. C++ 클래스 컨텍스트에서 콜백 함수를 사용하려면 정적 함수를 사용하여 콜백 핸들러를 등록할 수 있으며, this 포인터는 컨텍스트 데이터 포인터로 사용되어야 하며, 이를 다시 클래스 포인터로 캐스팅하여 그에 따라 사용할 수 있습니다.

동기식 이벤트 대기#

uint64_t Fg_eventWait(
    Fg_Struct * fg,
    uint64_t mask,
    unsigned int timeout,
    unsigned int flags,
    struct fg_event_info * info);

애플리케이션은 다음 함수를 호출하여 이벤트 소스 그룹의 이벤트를 동기적으로 대기할 수 있습니다. Fg_eventWait(). 파라미터 flags 를 사용하면 함수가 호출될 때마다 단일 이벤트만 반환될지 아니면 대기 중인 모든 이벤트가 그룹화될지 선택할 수 있습니다. 다음 값을 전달할 때의 기본 동작은 FG_EVENT_DEFAULT_FLAGS 파라미터에 flags 함수가 호출될 때마다 최대 하나의 이벤트를 반환하는 것입니다. 다음 값을 전달하면 FG_EVENT_BATCHED 대기 중인 모든 이벤트가 함께 그룹화됩니다. 이 함수는 파라미터에 지정된 이벤트 소스 중 하나에 대해 이벤트가 수신될 때까지 대기합니다. mask, 또는 파라미터에 지정된 초가 timeout 경과했습니다. 타임아웃이 발생할 때까지 수신된 이벤트가 없으면 함수는 0을 반환하며, 그렇지 않으면 수신된 이벤트 또는 이벤트 그룹이 포함된 마스크를 반환합니다.

이벤트 활성화#

int Fg_activateEvents(
    Fg_Struct * fg,
    uint64_t mask,
    int enable);

이벤트 소스가 이벤트를 전송하려면 먼저 활성화되어야 합니다. Fg_activateEvents() 를 호출하여 이벤트 소스 그룹을 활성화하거나 비활성화할 수 있습니다. 파라미터에 1이 전달되면 enable파라미터에 전달된 이벤트 소스 그룹 mask 이(가) 활성화됩니다. 파라미터에 0이 전달되면 enable비활성화됩니다. 애플리케이션에서 더 이상 사용하지 않는 모든 이벤트 소스는 비활성화해야 합니다.

이벤트 소스는 활성화된 후 언제든지 이벤트를 발생시킬 수 있으므로, Fg_registerEventCallback()을(를) 사용하여 콜백이 등록된 후 또는 별도의 스레드가 이벤트를 대기할 준비가 된 후에만 이벤트 소스를 활성화하는 것이 좋습니다. Fg_eventWait().

여러 프로세스에서 프레임 그래버 사용 지원#

일부 애플리케이션에서는 서로 다른 프로세스에서 단일 프레임 그래버에 접근해야 할 수 있습니다. 간단한 예로 획득 프로세스와 같은 다른 프로세스의 활동을 모니터링하는 프로세스가 있습니다. 또 다른 예로는 최대 4개의 카메라가 연결된 프레임 그래버에서 각각 하나의 카메라를 사용하는 개별 획득 프로세스가 있을 수 있습니다.

Framegrabber API는 마스터/슬레이브 모드를 통해 이러한 시나리오를 제한적으로 지원합니다. 마스터/슬레이브 프로세스를 사용할 때는 한계를 이해하는 것이 중요합니다. 또한 두 개 이상의 프로세스를 동기화해야 할 때 애플리케이션 개발자가 직면하는 일반적인 과제를 이해하는 것도 중요합니다. Framegrabber API는 여러 프로세스에서 프레임 그래버를 사용하는 기능을 지원하지만, 프레임 그래버를 초기화할 때 프로세스의 시작을 동기화하는 가장 기본적인 기능 외에는 프로세스 간 동기화를 지원하지 않습니다. 범용 프로세스 간 통신 및 동기화를 위해서는 다른 운영 체제 기능이나 지원 라이브러리를 사용해야 합니다.

master/slave 모드의 한 가지 특정한 제한 사항은 두 프로세스가 프레임 그래버의 동일한 기능을 제어하려고 할 때마다 마지막 프로세스가 "승리"하여 첫 번째 프로세스의 작업을 덮어쓴다는 점입니다. 첫 번째 프로세스는 덮어쓰인 사실조차 알아차리지 못하고 프레임 그래버의 상태에 대해 잘못된 가정할 수 있습니다. (프로세스 간 통신을 사용하여 프로세스 간의 상태를 동기화하는 실험적 기능이 존재하지만, 이 접근 방식에는 고유한 영향이 있으며 파라미터 및 Acquisition 동기화를 위한 실험적 지원 섹션에서 논의됩니다.)

일반적인 권장 사항은 프로세스가 고유한 작업(앱릿 파라미터 및 기능과 관련하여 상호 배타적인 작업)을 수행하고 다른 프로세스의 존재를 알 필요가 없도록 프로세스를 설계하는 것입니다. 예외적으로 모니터링 프로세스는 앱릿의 읽기 전용 기능에만 접근하거나 프로세스 간 통신 수단을 통해 다른 프로세스에서 정보를 수집합니다.

또 다른 한계는 마스터 프로세스만 프레임 그래버를 완전히 초기화하지만, 각 프로세스에서 기본 초기화가 수행되어야 한다는 점입니다. 이 기본 초기화는 이미 이미지 획득이나 카메라 검색을 시작한 이전 프로세스와 충돌을 일으킬 수 있습니다.

초기화 중 프로세스 동기화#

int Fg_InitLibrariesEx(
    const char * path,
    unsigned int flags,
    const char * id,
    unsigned int timeout);

void Fg_AbortInitLibraries();

void Fg_InitLibrariesStartNextSlave();
Fg_Struct * Fg_InitEx(
    const char * applet,
    unsigned int board,
    int flags);

Fg_Struct * Fg_InitConfigEx(
    const char * config,
    unsigned int board,
    int flags);

여러 프로세스를 동기화할 때 Framegrabber API가 제공하는 동기화 지점은 Fg_InitLibrariesEx()호출입니다. 와 마찬가지로 Fg_InitLibraries(), 호출의 첫 번째 파라미터는 사용되지 않으며 애플리케이션은 항상 nullptr.

동기화할 프로세스는 그룹을 형성하며 동기화는 그룹 내의 프로세스만 고려합니다. 동기화할 프로세스 그룹은 파라미터를 통해 식별됩니다. id. 이런 방식으로 복잡한 애플리케이션은 여러 개의 독립된 동기화 그룹을 가질 수 있습니다. 그룹을 식별하는 문자열은 비어 있지 않아야 하며, 사용 중인 운영 체제의 파일 이름에 허용되는 문자로만 구성되어야 합니다. 애플리케이션에서 사용하는 식별자를 siso- 로 시작하는 것은 권장되지 않으며, 접두사 siso- 은(는) Framegrabber API에서 사용하는 용도로 예약된 것으로 간주해야 합니다.

동기화 동작은 파라미터를 통해 설정할 수 있습니다. flags. 파라미터에서는 다음 값과 매크로를 사용할 수 있습니다. flags:

Flag 설명
FG_INIT_LIBRARIES_SINGLE 기본 초기화, 동기화 없음
FG_INIT_LIBRARIES_MASTER Master 초기화, slave 동기화 준비
FG_INIT_LIBRARIES_SLAVE Slave 초기화, master 대기
FG_INIT_LIBRARIES_SEQUENTIAL 엄격한 순차적 시작
FG_INIT_LIBRARIES_AUTOSTART_ON_INIT 프레임 그래버 초기화 시 다음 slave 시작
FG_INIT_LIBRARIES_SET_SLAVE_PRIORITY(n) 슬레이브 우선순위 설정
FG_INIT_LIBRARIES_SET_NUMBER_OF_SLAVES(n) 슬레이브 수 설정

사용 FG_INIT_LIBRARIES_SINGLE 은(는) 다음을 호출하는 것과 같습니다. Fg_InitLibraries().

사용 FG_INIT_LIBRARIES_SEQUENTIAL 은(는) 마스터 프로세스에서 우선순위가 가장 높은 슬레이브 프로세스만 시작합니다. 두 번째로 우선순위가 높은 슬레이브 프로세스는 우선순위가 가장 높은 슬레이브 프로세스에서 시작해야 하는 식입니다. 이를 통해 프로세스 초기화의 엄격한 순서가 보장됩니다. 만약 FG_INIT_LIBRARIES_SEQUENTIAL 동기화 그룹에서 사용되는 경우 마스터 프로세스를 포함한 모든 프로세스에 지정해야 합니다. 매크로 FG_INIT_LIBRARIES_SET_SLAVE_PRIORITY() 은(는) 다음이 사용될 때 모든 슬레이브 프로세스에서 사용되어야 하며 슬레이브 프로세스의 우선순위를 정의합니다. 최고 우선순위는 1이고 최저 우선순위는 63입니다. 그룹의 각 프로세스는 고유한 우선순위를 가져야 하며 빈틈이 없도록 우선순위를 할당해야 합니다. (프로세스 2가 프로세스 3을 시작하려고 하는데 프로세스 3이 없으면 아무도 프로세스 4를 시작하지 않습니다.) 매크로 FG_INIT_LIBRARIES_SEQUENTIAL 이 사용되며, 슬레이브 프로세스의 우선순위를 정의합니다. 가장 높은 우선순위는 1이고, 가장 낮은 우선순위는 63입니다. 한 그룹 내의 각 프로세스는 고유한 우선순위를 가져야 하며, 우선순위는 간격이 생기지 않도록 할당되어야 합니다. (프로세스 2가 프로세스 3을 시작하려고 하는데 프로세스 3이 없다면, 아무도 프로세스 4를 시작하지 않게 됩니다.) 이 매크로는 FG_INIT_LIBRARIES_SET_NUMBER_OF_SLAVES() 은(는) 다음이 사용될 때 마스터 프로세스에서 사용되어야 하며 슬레이브 프로세스의 수를 정의합니다. 허용되는 최소값은 1이고 최대값은 63입니다. FG_INIT_LIBRARIES_SEQUENTIAL 이 옵션은 슬레이브 프로세스의 수를 정의하는 데 사용됩니다. 허용되는 최소값은 1이며, 최대값은 63입니다.

호출의 마지막 파라미터는 Fg_InitLibrariesEx() 어플리케이션에 오류가보고되기 전에 프로세스가 스케줄링되기를 기다리는 시간을 밀리초 단위로 지정합니다.

일반적으로 마스터 프로세스라고 하는 그룹의 첫 번째 프로세스는 다음이 호출될 때 그룹을 설정합니다. Fg_InitLibrariesEx() . 일반적으로 슬레이브 프로세스라고 하는 모든 후속 프로세스는 스케줄링을 위해 Fg_InitLibrariesEx() 의 해당 호출에서 대기하도록 선택할 수 있습니다. 하나 이상의 슬레이브 시작은 마스터 프로세스의 Fg_InitLibrariesStartNextSlave() 호출에 의해 트리거됩니다. 함수 Fg_InitLibrariesStartNextSlave() 프로세스가 다음 호출을 통해 프레임 그래버를 초기화할 때 자동으로 호출될 수 있습니다. Fg_Init(), Fg_InitEx(), Fg_InitConfig() 또는 Fg_InitConfigEx().

함수 Fg_InitLibraries() 일반적인 상황에서는 실패하지 않아야 하지만 동기화를 사용할 때는 Fg_InitLibrariesEx() 의 경우 그렇지 않습니다. 대기 시간을 합리적으로 지정하고 그에 따라 오류를 처리하십시오.

멀티 스레드 응용 프로그램에서 Fg_InitLibrariesEx() 호출 대기는 Fg_AbortInitLibraries()을(를) 호출하여 다른 스레드에서 중단될 수 있습니다. 이로 인해 중단된 호출에서 보고된 오류가 발생합니다.

마스터 프로세스에서 Fg_Init() 또는 Fg_InitConfig() 호출을 사용하여 프레임 그래버를 초기화할 수 있는 반면 모든 슬레이브 프로세스는 둘 중 하나를 호출해야 합니다. Fg_InitEx() 또는 Fg_InitConfigEx() 그리고 전달 FG_INIT_FLAG_SLAVE 매개변수 내 flags. Fg_InitEx() 또는 Fg_InitConfigEx() 호출 FG_INIT_FLAG_DEFAULT 은(는) 다음을 호출하는 것과 같습니다. Fg_Init() 또는 Fg_InitConfig()각각.

다음 예제는 마스터 프로세스가 두 개의 슬레이브 프로세스를 사용하여 엄격한 순차적 스케줄링을 위해 동기화 그룹을 설정하는 방법을 보여줍니다. 마스터는 다음 호출을 사용합니다. Fg_InitLibrariesStartNextSlave() 추가적인 초기화 작업 이후에 첫 번째 슬레이브 프로세스를 시작하려면 다음과 같이 합니다:

const char * syncGroupId = "example";

int result =
    Fg_InitLibrariesEx(
        nullptr,
        FG_INIT_LIBRARIES_MASTER
            | FG_INIT_LIBRARIES_SEQUENTIAL
            | FG_INIT_LIBRARIES_SET_NUMBER_OF_SLAVES(2),
        syncGroupId,
        0);

if (result == FG_OK) {
    const char * applet = "Acq_SingleCXP12Area";

    Fg_Struct * fg = Fg_Init(applet, 0);
    if (fg != nullptr) {
        // further initialization ...

        Fg_InitLibrariesStartNextSlave();

        // use frame grabber ...
    }

    Fg_FreeLibraries();
}

예제의 슬레이브 프로세스는 호출에 지정된 우선순위를 제외하고는 모두 동일합니다. Fg_InitLibrariesEx(), 여기서는 첫 번째 슬레이브 프로세스만 표시됩니다. 슬레이브 프로세스는 다음과 같이 사용합니다. FG_INIT_LIBRARIES_AUTOSTART_ON_INIT 다음을 호출할 때 다음 슬레이브 프로세스를 암시적으로 시작합니다: Fg_InitEx() 가 호출됩니다:

const char * syncGroupId = "example";

int result =
    Fg_InitLibrariesEx(
        nullptr,
        FG_INIT_LIBRARIES_SLAVE
            | FG_INIT_LIBRARIES_SEQUENTIAL
            | FG_INIT_LIBRARIES_AUTOSTART_ON_INIT
            | FG_INIT_LIBRARIES_SET_SLAVE_PRIORITY(1),
        syncGroupId,
        10000);

if (result == FG_OK) {
    const char * applet = "Acq_SingleCXP12Area";

    Fg_Struct * fg = Fg_InitEx(applet, 0, FG_INIT_FLAG_SLAVE);
    if (fg != nullptr) {
        // use frame grabber ...
    }

    Fg_FreeLibraries();
}

슬레이브 프로세스가 마스터 프로세스보다 먼저 시작되면, 마스터 프로세스가 시작될 때까지 다음 호출에서 대기합니다. Fg_InitLibrariesEx() 마스터 프로세스가 시작되기를 기다립니다. 마스터 프로세스가 호출되면 Fg_InitLibrariesStartNextSlave() 슬레이브 프로세스가 실행되도록 예약되고 다음 호출이 수행됩니다. Fg_InitLibrariesEx() 반환 값: FG_OK. 마스터 프로세스가 시작되지 않거나 슬레이브의 대기 시간이 만료되기 전에 초기화를 완료하지 못하면 슬레이브가 실행되도록 예약될 수 없으며 다음 호출이 수행됩니다. Fg_InitLibrariesEx() 에서 타임아웃 오류가 반환됩니다.

Framegrabber SDK와 함께 설치되는 microDisplay X 툴은 마스터/슬레이브 동기화를 지원하며, 슬레이브 프로세스는 그룹 ID를 사용하여 microDisplay X와 동기화할 수 있습니다. siso-microdisplay-master. 다음 플래그는 FG_INIT_LIBRARIES_SEQUENTIAL 은(는) microDisplay X에서 지원되지 않습니다.

파라미터 및 Acquisition 동기화에 대한 실험적 지원#

정보

파라미터 및 취득 동기화에 대한 실험적 지원은 Framegrabber SDK 버전 5.9에 추가되었습니다.

Framegrabber API는 프로세스 동기화 그룹 전반에서 모든 파라미터 변경 및 취득 상태를 동기화하기 위한 실험적 지원을 제공합니다. 파라미터 및 취득 동기화를 활성화하려면 FG_INIT_FLAG_PARAM_SYNC 을(를) 파라미터에 추가해야 합니다. flags 호출 시 Fg_InitEx() 또는 Fg_InitConfigEx() 그룹의 모든 프로세스에 적용됩니다.

그러나 파라미터 및 취득 동기화를 사용할 때 고려해야 할 몇 가지 사항이 있습니다.

첫째, Framegrabber API가 제공하는 동기화는 운영 체제에서 제공하는 프로세스 간 통신 메커니즘을 사용합니다. 파라미터를 가져오고 설정하는 작업이 프로세스 내에서 로컬로 수행되지 않고 여러 프로세스 간에 동기화되어야 하므로 이러한 작업의 지연 시간(latency)과 지터(jitter)가 모두 증가합니다. 대부분의 응용 프로그램에서는 이러한 단점이 문제가 되지 않습니다. 그러나 응용 프로그램이 실시간 운영 체제를 사용하고 하나 이상의 파라미터를 가져오거나 설정하는 작업이 실시간으로 중요한 경우 파라미터 및 취득 동기화를 활성화해서는 안 됩니다. 만약 FG_INIT_FLAG_PARAM_SYNC 을(를) 명시적으로 사용하지 않는 경우, 파라미터 및 취득 동기화가 활성화되지 않으며 이 실험적 기능은 이전 버전의 Framegrabber API와 비교하여 성능에 영향을 미치지 않습니다.

둘째, 동기화를 사용할 때 마스터 프로세스 또는 슬레이브 프로세스 중 하나만 취득을 제어할 수 있으며 두 프로세스 모두 제어할 수는 없습니다. 동기화 그룹 내에서 마스터 프로세스의 취득을 하나 이상의 슬레이브 프로세스의 취득과 혼용할 수 없습니다. 대부분의 경우 취득은 하나 이상의 슬레이브 프로세스에서 수행되어야 하며, FG_INIT_FLAG_ACQUISITION_SLAVE 을(를) 파라미터에 추가해야 합니다. flags 호출 시 Fg_InitEx() 또는 Fg_InitConfigEx() 마스터 프로세스용입니다.

비균일 메모리 접근(NUMA) 지원#

int Fg_NumaPinThread(
    Fg_Struct * fg);

void * Fg_NumaAllocDmaBuffer(
    Fg_Struct * fg,
    size_t size);

int Fg_NumaFreeDmaBuffer(
    Fg_Struct * fg,
    void * ptr);

비균등 메모리 접근(NUMA)을 사용하는 다중 프로세서 컴퓨터에서는 각 물리적 프로세서가 자체 메모리 및 주변기기 버스를 가집니다. 프로세스가 실행 중인 동일한 물리적 프로세서의 자원만 접근하는 한, 접근 속도는 단일 프로세서 컴퓨터와 거의 비슷하며 대칭형 멀티프로세싱(SMP)을 사용하는 다중 프로세서 컴퓨터보다 훨씬 빠릅니다. 그러나 한 물리적 프로세서에서 실행 중인 프로세스가 다른 물리적 프로세서에 속한 자원에 접근하려는 경우 데이터가 두 물리적 프로세서 간에 이동해야 하므로 접근 속도가 느려집니다. 자세한 내용은 Wikipedia의 비균등 메모리 접근 문서를참조하십시오.

NUMA 컴퓨터에서 실행되는 애플리케이션을 지원하기 위해, 프레임 그래버에 액세스하는 모든 스레드는 장치가 로컬로 연결된 물리적 프로세서에 고정(pinned)되어야 합니다. 이는 다음을 호출하여 수행할 수 있습니다. Fg_NumaPinThread() 프레임 그래버에서 파라미터에 액세스하거나 제어를 수행하는 각 스레드의 컨텍스트에서 호출합니다.

또한 메모리 역시 동일한 물리적 프로세서에 로컬로 할당되어야 합니다. 애플리케이션이 Framegrabber API에서 제공하는 할당 함수를 사용하는 경우 이 작업은 자동으로 수행됩니다. 그러나 애플리케이션이 다음을 사용하는 경우 Fg_AllocMemHead() 및 Fg_AddMem()NUMA 인식 메모리 할당을 사용하여 메모리를 할당해야 합니다. Framegrabber API는 다음 함수를 제공합니다. Fg_NumaAllocDmaBuffer() 및 Fg_NumaFreeDmaBuffer() 프레임 그래버가 로컬로 연결된 동일한 물리적 프로세서에서 메모리를 할당하고 해제합니다.

애플리케이션이 메모리 할당을 위해 다른 NUMA 인식 함수를 사용하는 경우, 다음 함수를 호출할 수 있습니다. Fg_getIntSystemInformationForBoardIndex() 다음과 함께 호출 INFO_DRIVERGROUPAFFINITY 드라이버 IRQ 그룹 친화성(affinity)을 제공하고, 다음 함수는 Fg_getInt64SystemInformationForBoardIndex() 다음과 함께 호출 INFO_DRIVERAFFINITYMASK 장치에 대한 드라이버 IRQ 프로세서 친화성 마스크를 제공합니다.

일부 NUMA 컴퓨터에는 다른 제약 사항이 있을 수도 있습니다. 예를 들어 일부 NUMA 컴퓨터는 주변 장치 버스에 대한 액세스 균형을 맞추도록 설계되어 단일 장치가 대역폭의 전부 또는 대부분을 사용하는 것을 허용하지 않습니다. 이는 대부분의 서버 애플리케이션에는 유익하지만, 이미지 취득 및 처리 애플리케이션의 경우 이 전략으로 인해 프레임 그래버 장치에서 사용할 수 있는 대역폭이 제한될 수 있습니다.

Plain C 사용 시 고려 사항#

애플리케이션이 일반 C 컴파일러 사용으로 제한되는 경우, Framegrabber API가 편의성이나 형식 안전성(type-safety)을 위해 제공하는 일부 C++ 래퍼를 사용할 수 없습니다. 이 장에서는 C++ 래퍼가 사용하는 기본 기능을 사용하는 방법을 각 주제별로 설명합니다.

Plain C에서의 시스템 정보#

int Fg_getSystemInformation(
    Fg_Struct * fg,
    enum Fg_Info_Selector info,
    enum FgProperty property,
    int arg,
    void * buffer,
    unsigned int * size);

섹션 일반 시스템 정보 및 보드별 시스템 정보 챕터 시스템 정보 에는 시스템 일반 또는 특정 프레임 그래버에 대한 다양한 정보를 요청하는 일련의 함수가 문서화되어 있습니다. 이 두 장의 함수는 모두 다음 함수의 C++ 래퍼입니다. Fg_getSystemInformation().

함수 Fg_getSystemInformation() 요청된 정보를 함수에 전달된 버퍼에 저장되는 문자열로 항상 반환합니다. 충분한 크기의 버퍼를 할당하기 위해, 파라미터에 사용되는 변수를 초기화하여 버퍼의 크기를 요청할 수 있습니다. size 0으로 설정하고 호출 시 다음을 전달합니다. NULL 파라미터에 buffer 요청된 정보가 숫자 형식인 경우, 정보를 성공적으로 요청한 후 문자열을 변환해야 합니다.

섹션 일반 시스템 정보, 함수 Fg_getSystemInformation() 다음과 함께 호출 NULL 파라미터에 전달 fg 파라미터에 0을 전달 arg.

예를 들어, 컴퓨터에 설치된 프레임 래퍼의 수는 아래와 같이 요청할 수 있습니다.

int numBoards = 0;
char buffer[256];
unsigned int size = sizeof(buffer);
int result =
    Fg_getSystemInformation(NULL, INFO_NR_OF_BOARDS, PROP_ID_VALUE,
                            0, buffer, &size);
if (result == FG_OK) {
    numBoards = atoi(buffer);
    std::cout << "Number of boards: " << numBoards << std::endl;
}

섹션 보드별 시스템 정보, 함수 Fg_getSystemInformation() 파라미터에 전달된 프레임 그래버에 대한 핸들 fg또는 파라미터에 전달된 보드 인덱스가 필요합니다. arg.

예를 들어 다음 코드는 보드 유형과 이름을 요청합니다.

const int boardIndex = 0;

char buffer[256];
unsigned int size = sizeof(buffer);

int boardType = 0;
std::string boardName;
int result =
    Fg_getSystemInformation(NULL, INFO_BOARDTYPE, PROP_ID_VALUE,
                            boardIndex, buffer, &size);
if (result == FG_OK) {
    boardType = atoi(buffer);

    size = sizeof(buffer);
    result =
        Fg_getSystemInformation(NULL, INFO_BOARDNAME, PROP_ID_VALUE,
                                boardIndex, buffer, &size);
}
if (result == FG_OK) {
    boardName = buffer;

    std::cout << "Board #" << boardIndex
              << " is a " << boardName
              << " (type " << std::hex << boardType
              << std::dec << ")" << std::endl;
}

입력 시 추가 인수가 필요한 정보를 요청하는 경우, 버퍼는 양방향으로 작동합니다. 호출 전에 추가 인수가 문자열로 버퍼에 저장되어야 합니다. 호출 중에 버퍼에 전달된 인수가 사용된 후 덮어쓰여지며, 요청된 정보가 버퍼에 기록됩니다.

Plain C에서 파라미터 값 액세스#

int Fg_getParameterWithType(
    Fg_Struct * fg,
    int id,
    void * value,
    unsigned int dma,
    enum FgParamTypes type);

int Fg_freeParameterStringWithType(
    Fg_Struct * fg,
    int id,
    void * value,
    unsigned int dma,
    enum FgParamTypes type);
int Fg_setParameterWithType(
    Fg_Struct * fg,
    int id,
    const void * value,
    unsigned int dma,
    enum FgParamTypes type);

섹션 파라미터 값 액세스 챕터 Applet 파라미터 작업에는 가장 일반적인 타입의 파라미터를 요청하기 위한 C++ 래퍼가 문서화되어 있습니다. 일반 C에서 파라미터에 접근하거나 C++ 래퍼가 존재하지 않는 타입의 파라미터에 접근하려면 함수 Fg_getParameterWithType() 및 Fg_setParameterWithType() 사용할 수 있습니다. 호출을 위해서는 일치하는 타입의 변수가 필요하며, 해당 FgParamTypes 값은 호출 시 매개변수 type 를 호출 시 사용합니다. 타입 값은 섹션 파라미터 유형 에 문서화되어 있으며, 특정 파라미터의 타입을 확인하려면 애플릿 문서를 참조해야 합니다.

예를 들어, 다음 코드는 앱릿의 첫 번째 DMA 채널 너비를 1024로 설정합니다.

const int dma = 0;
const int width = 1024;
int result = FG_INVALID_PARAMETER;
int paramId = Fg_getParameterIdByName(fg, "FG_WIDTH");
if (paramId > 0) {
    result =
        Fg_setParameterWithType(fg, paramId, &width, dma,
                                FG_PARAM_TYPE_INT32_T);
}

호출 시 발생하는 한 가지 특수한 경우는 Fg_getParameterWithType() 이며, 이는 문자열 매개변수를 나타내는 FG_PARAM_TYPE_CHAR_PTR 타입입니다. 충분한 크기의 버퍼를 할당하는 데 필요한 문자열의 길이는 호출을 통해 요청할 수 있지만 Fg_getParameterPropertyEx(), 이는 동적 매개변수에 접근하는 가장 안전한 방법은 아닙니다. 더 나은 접근 방식은 대신 FG_PARAM_TYPE_CHAR_PTR 사용 FG_PARAM_TYPE_CHAR_PTR_PTR 타입의 매개변수를 요청하는 것입니다. 이 요청은 적절한 크기의 버퍼를 할당하며, 값이 더 이상 필요하지 않은 후에 Fg_freeParameterStringWithType() 을(를) 호출하여 해제할 수 있습니다.

다음 예제는 FG_PARAM_TYPE_CHAR_PTR_PTR을(를) 사용하는 방법을 보여줍니다. 단, paramId 이(가) FG_PARAM_TYPE_CHAR_PTR:

const char * val = NULL;
int result =
    Fg_getParameterWithType(fg, paramId, &val, dma,
                            FG_PARAM_TYPE_CHAR_PTR_PTR);
if (result == FG_OK) {
    // use the string value stored in val ...

    Fg_freeParameterStringWithType(fg, paramId, val, dma,
                                   FG_PARAM_TYPE_CHAR_PTR_PTR);
}

타입의 매개변수라고 가정합니다. Fg_freeParameterStringWithType() 호출은 char *을(를) 수신하며, 실제로는 char **.

필드 파라미터 액세스#
struct FieldParameterAccess {
    enum FgParamTypes vtype;
    unsigned int index;
    unsigned int count;
    union {
        int32_t * p_int32_t;
        uint32_t * p_uint32_t;
        int64_t * p_int64_t;
        uint64_t * p_uint64_t;
        double * p_double;
    };
};

이(가) 아닙니다. 필드 매개변수는 동일한 타입의 두 개 이상 값 배열을 나타내는 매개변수입니다. 대표적인 예로는 픽셀 값을 재매핑하는 데 사용할 수 있는 룩업 테이블이 있습니다. 필드 매개변수는 다음 타입일 수 있습니다: FG_PARAM_TYPE_STRUCT_FIELDPARAMINT, FG_PARAM_TYPE_STRUCT_FIELDPARAMINT64 또는 FG_PARAM_TYPE_STRUCT_FIELDPARAMDOUBLE.

필드 매개변수의 크기는 Working with Applet Parameters 챕터의 Accessing Parameter Properties 섹션에 문서화된 대로 매개변수 Property PROP_ID_FIELD_SIZE 섹션 파라미터 Property 액세스 챕터 Applet 파라미터 작업에 문서화된 바와 같습니다. 필요한 경우 Plain C에서 파라미터 Property 액세스 섹션도 참조하십시오.

필드 매개변수의 배열에서 값을 요청하거나 변경하려면 함수 Fg_getParameterWithType() 및 Fg_setParameterWithType() 을(를) 호출해야 합니다. 이때 인스턴스를 사용해야 하며, struct FieldParameterAccess 및 FG_PARAM_TYPE_STRUCT_FIELDPARAMACCESS 은(는) 매개변수 type에 전달되어야 합니다. vtype 의 멤버 struct FieldParameterAccess 은(는) 다음으로 설정해야 합니다. enum FgParamTypes 필드의 단일 값 유형에 해당하는 값이며, 필드 파라미터 유형 자체가 아닙니다. 멤버는 index 및 count 필드 파라미터의 배열 오프셋과 함수 호출에서 요청되거나 제공된 항목 수를 지정합니다. 마지막으로, 필드의 단일 값 유형에 해당하는 유니온의 포인터는 다음과 같은 경우 입력 시 변경될 값을 포함하는 사전 할당된 버퍼로 초기화되어야 합니다. Fg_setParameterWithType() 이 호출되거나, 또는 다음과 같은 경우 배열에 현재 저장된 값들이 반환됩니다. Fg_getParameterWithType() 이 호출되었습니다.

다음 예제는 다음과 같이 가정할 때 룩업 테이블의 처음 256개 값을 요청합니다. paramId 이(가) FG_PARAM_TYPE_STRUCT_FIELDPARAMINT 그리고 필드 자체는 다음과 같은 유형의 256개 이상의 값으로 구성됩니다. FG_PARAM_TYPE_INT32_T:

int32_t field[256];
struct FieldParameterAccess fpa;
fpa.vtype = FG_PARAM_TYPE_INT32_T;
fpa.index = 0;
fpa.count = 256;
fpa.p_int32_t = &field;
int result =
    Fg_getParameterWithType(fg, paramId, &fpa, dma,
                            FG_PARAM_TYPE_STRUCT_FIELDPARAMACCESS);
if (result == FG_OK) {
    // work with the values in field ...
}

Plain C에서 파라미터 Property 액세스#

int Fg_getParameterProperty(
    Fg_Struct * fg,
    int id,
    enum FgProperty property,
    void * buffer,
    int * size);

int Fg_getParameterPropertyEx(
    Fg_Struct * fg,
    int id,
    enum FgProperty property,
    int dma,
    void * buffer,
    int * size);

섹션 파라미터 Property 액세스 챕터 Applet 파라미터 작업에는 가장 일반적인 타입의 파라미터 Property를 요청하기 위한 C++ 래퍼가 문서화되어 있습니다. 일반 C에서 파라미터 Property에 접근하거나 C++ 래퍼가 존재하지 않는 타입의 파라미터 Property에 접근하려면 함수 Fg_getParameterPropertyEx() 함수를 사용하는 것은 Fg_getParameterProperty() 함수 호출이 암시적으로 DMA 채널 0을 사용하므로 권장되지 않습니다. 단, 파라미터 Property는 채널에 따라 다를 수 있습니다.

함수 Fg_getParameterPropertyEx() 은(는) 한 가지 경우를 제외하고 요청된 정보를 함수에 전달된 버퍼에 저장되는 문자열로 반환합니다. 충분한 크기의 버퍼를 할당하기 위해, 파라미터에 사용되는 변수를 초기화하여 버퍼의 크기를 요청할 수 있습니다. size 0으로 설정하고 호출 시 다음을 전달합니다. NULL 파라미터에 buffer 요청된 정보가 숫자 형식인 경우, 정보를 성공적으로 요청한 후 문자열을 변환해야 합니다.

다음 예제는 paramId가 다음 타입의 파라미터라고 가정할 때 파라미터의 최솟값을 가져오는 방법을 보여줍니다. FG_PARAM_TYPE_INT32_T:

char buffer[256];
int size = sizeof(buffer);

int32_t minVal = 0;
int result =
    Fg_getParameterPropertyEx(fg, paramId, PROP_ID_MIN, dma, buffer, &size);
if (result == FG_OK) {
    minVal = atoi(buffer);

    // work with the property ...
}
Enum 값 파라미터 Property 접근#
struct FgPropertyEnumValues {
    int32_t value;
    char name[1];
};

#define FG_PROP_GET_NEXT_ENUM_VALUE(pev) ...

Property을(를) 요청할 때 PROP_ID_ENUM_VALUES 열거형 파라미터의 경우,에 대한 호출은 Fg_getParameterPropertyEx() Property을(를) 문자열로 반환하지 않습니다. 대신 버퍼가 다음을 사용하여 채워집니다. struct FgPropertyEnumValues. 매크로 FG_PROP_GET_NEXT_ENUM_VALUE() 은(는) 버퍼의 요소를 반복하는 데 사용할 수 있습니다. 편의를 위해 Property PROP_ID_IS_ENUM 은(는) 열거형 파라미터에 필요한 버퍼의 크기를 반환합니다.

다음 예제는 paramId가 열거형 파라미터라고 가정할 때 파라미터의 enum values Property를 가져와 출력하는 방법을 보여줍니다.

const int defBufferSize = 256;

int size = defBufferSize;
char * buffer = malloc(size);

int result =
    Fg_getParameterPropertyEx(fg, paramId, PROP_ID_IS_ENUM,
                              dma, buffer, &size);
if (result == FG_OK) {
    int newSize = atoi(buffer);
    if (newSize > 0) {
        free(buffer);
        size = newSize;
        buffer = malloc(size);

        result =
            Fg_getParameterPropertyEx(fg, paramId, PROP_ID_ENUM_VALUES,
                                      dma, buffer, &size);
    } else {
        result = FG_INVALID_TYPE;
    }
}
if (result == FG_OK) {
    struct FgPropertyEnumValues * pev;
    for (pev = (struct FgPropertyEnumValues *)buffer;
         pev != NULL;
         pev = FG_PROP_GET_NEXT_ENUM_VALUE(pev)) {
            printf("%s is %d\n", pev->name, pev->value);
    }
}
free(buffer);

Plain C에서 비동기 모드를 위한 콜백 함수 등록#

struct FgApcControl {
    unsigned int version;
    Fg_ApcFunc_t func;
    void *data;
    unsigned int timeout;
    unsigned int flags;
};

int Fg_registerApcHandler(
    Fg_Struct * fg,
    unsigned int dma,
    struct FgApcControl * control,
    enum FgApcControlFlags flags);

함수 Fg_registerApcHandler() 획득을 시작하기 전에 비동기 모드를 설정하는 데 사용할 수 있습니다.

콜백 함수는 섹션 비동기 모드용 콜백 함수 등록 챕터 이미지 취득에 문서화된 것과 동일한 방식으로 작동합니다. 함수 Fg_registerCallbackHandler() 획득 루프를 제어하는 파라미터가 다음의 인스턴스에 전달됩니다. struct FgApcControl, 반면에 C++ 래퍼 함수를 호출할 때 Fg_registerApcHandlerEx() 이러한 파라미터는 함수의 인자로 전달됩니다.

콜백 함수를 등록할 때 플래그가 전달되는 곳은 두 군데입니다. 파라미터 flags 함수의 Fg_registerApcHandler() 은(는) 획득 루프를 제어하지 않으며 사용되지 않습니다. 응용 프로그램은 항상 이 파라미터에 0을 전달해야 합니다. 대신, 획득 루프를 제어하는 플래그는 동일한 프레임 그래버 핸들과 DMA 채널을 사용하되 다음을 전달하여 멤버에 전달됩니다. flags 의 멤버 struct FgApcControl.

다음 예제는 이미지 수집 처리에 필요한 정보를 담고 있는 간단한 구조체를 사용하여 콜백 함수를 등록하는 방법을 보여줍니다.

struct ApcUserCallbackData
{
    Fg_Struct * fg;
    dma_mem * mem;
    unsigned int dma;
    unsigned int timeoutInSeconds;
    int mode;
};

int ApcUserCallback(frameindex_t frame, void * data)
{
    auto context = reinterpret_cast<ApcUserCallbackData *>(data);

    if (frame > 0) {
        // process new image ...
    } else {
        // handle error ...
    }

    return 0;
}

void SetupApcUserCallback(ApcUserCallbackData * context)
{
    // register callback function
    FgApcControl control;
    control.version = 0;
    control.func = &ApcUserCallback;
    control.data = context;
    control.timeout = context->timeoutInSeconds;
    control.flags = FG_APC_DELIVER_ERRORS | FG_APC_IGNORE_TIMEOUTS;

    int result = Fg_registerApcHandler(
        context->fg, context->dma, &control, 0);
    if (result != FG_OK) {
        throw std::runtime_error("Failed to register callback function");
    }
}

컨텍스트 구조의 할당 및 관리는 예제에 표시되지 않습니다. 포인터는 콜백 함수가 등록되어 있는 동안 유효해야 합니다. 한 가지 해결책은 C++ 클래스 내에서 모든 것을 함께 유지하는 것입니다. C++ 클래스 컨텍스트에서 콜백 함수를 사용하려면 정적 함수를 사용하여 콜백 핸들러를 등록할 수 있으며, this 포인터는 컨텍스트 데이터 포인터로 사용되어야 하며, 이를 다시 클래스 포인터로 캐스팅하여 그에 따라 사용할 수 있습니다.

콜백 함수가 더 이상 필요하지 않게 되면 다음을 호출하여 등록을 해제할 수 있습니다. Fg_registerApcHandler() NULL 파라미터에 func:

int result = Fg_registerApcHandler(context->fg, context->dma, NULL, 0);

Plain C에서 비동기 이벤트 처리를 위한 콜백 함수 등록 해제#

int Fg_registerEventCallback(
    Fg_Struct * fg,
    uint64_t mask,
    Fg_EventFunc_t handler,
    void * data,
    unsigned int flags,
    struct fg_event_info * info);

사용 Fg_registerEventCallback(), 다음 유형의 함수 Fg_EventFunc_t 를 호출하여 콜백 함수를 등록하면, 섹션 비동기 이벤트 처리를 위한 콜백 함수 등록 챕터 이미지 취득.

콜백 함수가 더 이상 필요하지 않게 되면 다음을 호출하여 등록을 해제할 수 있습니다. Fg_registerEventCallback(), 동일한 이벤트 그룹에 대한 마스크를 전달하며, FG_EVENT_DEFAULT_FLAGS 파라미터에 flags 및 NULL 파라미터에 handler, data 및 info:

// unregister event handler
Fg_registerEventCallback(fg, mask, NULL, NULL, FG_EVENT_DEFAULT_FLAGS, NULL);

  1. 에 설명된 대로 이벤트 소스 그룹에서 하나 이상의 이벤트가 수신될 때 콜백이 호출되도록 등록할 수 있습니다. 그룹 코드는 라이선스의 각 기능에 비트가 대응하는 비트 필드입니다. 이 맥락에서 상위 집합(Superset)이란 애플릿 그룹 코드의 모든 비트에 대해 프레임 그래버 그룹 코드에서도 해당 비트가 설정되어 있어야 함을 의미합니다. 하위 집합(Subset)이란 맥락에서는 애플릿 그룹 코드의 모든 비트에 대해 프레임 그래버 그룹 코드에서도 해당 비트가 설정되어야 함을 의미합니다. 애플릿이 프레임 그래버의 라이선스를 통해 활성화되지 않은 기능을 사용하는 경우, Framegrabber SDK에서 해당 애플릿을 로드할 수 없습니다. ↩↩

  2. 파라미터의 값은 다음 범위 내의 임의의 값으로 설정할 수 있습니다. [PROP_ID_MIN; PROP_ID_MAX] 단위로, PROP_ID_STEP 다음 선형 관계에 따라 PROP_ID_VALUE = PROP_ID_MIN + n*PROP_ID_STEP, 여기서 n은 [0; (PROP_ID_MAX-PROP_ID_MIN)/PROP_ID_STEP[. ↩︎↩︎↩︎

  3. 이전 버전의 Framegrabber API에서는 다음을 사용했습니다. Fg_getLastPicNumberBlockingEx() 사용되는 acquisition 모델과 관계없이 acquisition 루프에서, 언제 ACQ_BLOCK 을(를) 사용하는 경우, 새로운 기본 동작은 다음을 호출하는 것입니다. Fg_getImageEx() 호출 SEL_ACT_IMAGE 언제 FG_APC_BATCH_IMAGES 이(가) 설정되고 SEL_NEXT_IMAGE 그렇지 않은 경우는 다음과 같습니다. 즉, ACQ_BLOCK, 기본 동작이 사용될 때 콜백 핸들러는 프레임 번호가 아닌 버퍼 번호를 수신합니다. 사용할 때 특정 프레임 번호에 대한 버퍼 번호를 안전하게 결정할 방법이 없으므로 ACQ_BLOCK에서, FG_APC_OLD_ACQ_BLOCK_BEHAVIOR 및 호출 Fg_getImageEx() 콜백 핸들러에서 호출하는 것은 권장되지 않으며, 애플리케이션 코드의 하위 호환성이 절대적으로 필요한 경우에만 사용해야 합니다. ↩︎↩︎