콘텐츠로 바로 가기

fglib5#

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

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

#include <basler_fg.h>

추가로, fglib5.lib 을(를) Microsoft Visual Studio 프로젝트에 추가해야 하며, Linux 프로젝트의 경우 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를 요청할 수 없습니다.

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

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

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

본 문서의 나머지 부분에 있는 코드 예제에는 애플리케이션의 요구 사항에 따라 달라지는 오류 처리가 포함되지 않습니다. 그러나 가능한 한 함수가 성공적으로 실행되었는지 반환 코드를 확인합니다.

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();

시스템 정보#

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

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

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

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 섹션을 참조하십시오.

지정된 프레임 grabber에 대해 대부분의 기타 정보는 다음 함수를 통해 요청할 수 있습니다. Fg_getIntSystemInformationForBoardIndex(), Fg_getInt64SystemInformationForBoardIndex() 및 Fg_getStringSystemInformationForBoardIndex() 보드 인덱스 또는 프레임 grabber 핸들과 다음 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 그룹 친화성(비균일 메모리 접근 지원 참조) int32_t
INFO_DRIVERAFFINITYMASK 드라이버 IRQ 프로세서 친화성 마스크(비균일 메모리 접근 지원 참조) 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 애플릿의 HAP ID(애플릿 경로는 arg 인자에 전달되어야 함) string
INFO_APPLET_BITSTREAM_ID 애플릿의 비트스트림 ID(애플릿 경로는 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

위 목록은 전체가 아니며 애플리케이션에 유용한 정보에 대한 속성만 포함합니다. 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;
}

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

정보 설명 Type
INFO_APPLET_CAPABILITY_TAGS applet 기능을 설명하는 키-값 쌍 목록 string
INFO_OWN_BOARDINDEX 프레임 grabber의 보드 인덱스 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 레퍼런스를 참조하십시오.

보드 인덱스 사용#

프레임 grabber는 보드 인덱스를 사용하여 선택됩니다. 시스템에 있는 보드 수를 아는 경우, 기본적으로 첫 번째 보드는 인덱스 0으로, 두 번째 보드는 인덱스 1로 식별되는 방식입니다.

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

Applets#

프레임 그래버를 사용하려면 앱릿이 필요합니다. 앱릿은 일반적으로 다음 여러 요소들의 모음입니다.

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

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

각 앱릿은 제공된 기능을 구성하기 위한 일련의 Property를 제공합니다. 앱릿이 제공하는 기능과 Property에 대한 자세한 내용은 사용할 특정 앱릿의 문서를 참조하십시오.

올바른 Applet 선택#

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

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

예를 들어, 앱릿 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 라이브러리를 초기화하기 시작할 때, ‘프레임 그래버 초기화’ 항목에 설명된 바와 같이 애플릿이 로드되기 전부터 프레임 그래버에 대한 액세스가 필요합니다. 이는 예를 들어, 보드를 일련번호별로 정렬하거나 로드 가능한 모든 애플릿을 확인하기 위해 필수적입니다.

이 초기화에 사용되는 applet은 사용하는 프레임 grabber에 따라 다릅니다. 다음 섹션의 정보를 사용하여 미리 정의된 applet으로 시작하도록 프레임 grabber를 구성할 수 있습니다. 미리 정의된 applet과 다른 applet을 사용할 때 호출 Fg_Init 시작 시간이 길어집니다.

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

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

microEnable 5 marathon Frame Grabbers의 시작 동작#

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

microEnable 6 Frame Grabbers의 시작 동작#

CXP-12 Interface Card, imaWorx CXP-12 Quad, imaFlex CXP-12 Quad 또는 imaFlex CXP-12 Penta 프레임 그래버에서 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 프레임 그래버를 나타내며, driver index 1 는 두 번째 보드를 나타내는 식입니다. 다른 모든 운영 체제에서는 드라이버 인덱스가 재정렬 없이 보드 인덱스와 동일합니다.

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

프레임 그래버에 대한 구성 파일을 찾을 수 없거나 초기화에 실패한 경우 기본 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 iterator의 항목은 다음을 호출하여 검색할 수 있습니다. 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 애플릿 사용 시 액세스할 수 있는 최대 카메라 수 int32_t
FG_AP_INT_GROUP_CODE 애플릿 라이선스 그룹 코드(프레임 그래버 라이선스 그룹 코드의 하위 집합이어야 함a) int32_t
FG_AP_INT_USER_CODE 애플릿 라이선스 사용자 코드(프레임 그래버 라이선스 사용자 코드와 일치해야 함) int32_t
FG_AP_INT_DESIGN_VERSION FPGA 디자인의 주 버전 int32_t
FG_AP_INT_DESIGN_REVISION FPGA 디자인의 버전 리비전 int32_t
FG_AP_STRING_APPLET_UID 애플릿 파일을 식별하는 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 iterator를 사용한 후에는 다음을 호출하여 해제해야 합니다. Fg_freeAppletIterator().

이름이 고유하고 표준 위치 중 한 곳에 applet이 있는 경우, 후속 호출에서 frame grabber를 초기화하는 데 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 초기화#

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

int Fg_FreeGrabber(
    Fg_Struct * fg);

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

애플리케이션이 frame grabber 사용을 마친 후에는 다음을 호출하여 해제해야 합니다. Fg_FreeGrabber().

예를 들어, 다음 코드는 applet을 사용하여 CXP-12 frame grabber를 초기화합니다. 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를 사용하여 frame grabber를 초기 설정하고 설정을 테스트하는 경우, 프로그램 내에서 구성을 저장할 수 있습니다. 메인 구성 파일의 확장자는 다음과 같습니다. .mcf 그리고 확장자가 다음과 같은 두 번째 파일이 .mfs 함께 생성됩니다. 이 두 파일을 사용하면 API 호출을 통해 구성을 다시 만들 필요 없이, 애플리케이션이 이 두 파일을 사용하여 직접 frame grabber를 초기화할 수 있습니다.

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

정보

함수의 매개변수에는 확장자가 다음과 같은 메인 구성 파일만 .mcf 사용됩니다. 확장자를 제외한 파일 이름이 동일한 경우, .mfs 확장자를 가진 파일이 자동으로 사용됩니다.

구성 파일에서 frame grabber를 초기화하려면 Fg_InitConfig() 대신 다음 함수를 Fg_Init()호출할 수 있습니다. 이 함수는 지정된 메인 구성 파일에 따라 frame grabber를 초기화한 후, 지정된 보드 인덱스에 대한 frame grabber 핸들을 반환합니다.

애플리케이션이 frame grabber 사용을 마친 후에는 다음을 호출하여 해제해야 합니다. Fg_FreeGrabber().

애플리케이션에 서로 다른 구성 세트가 필요한 경우, 다음을 호출하여 Fg_loadConfig() 다음 함수를 호출한 후 Fg_Init() 또는 Fg_InitConfig().

언제든지 frame grabber에 적용할 수 있습니다. 현재 구성은 다음을 호출하여 Fg_saveConfig() 다음 함수를 호출한 후 Fg_Init() 또는 Fg_InitConfig().

구성 파일에 기록할 수 있습니다. 다음 예제는 frame grabber의 구성을 저장하고 복원하는 방법을 보여줍니다.

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을 사용하여 frame grabber가 초기화되면 applet의 매개변수를 읽거나 조작할 수 있습니다. 예를 들어 카메라에서 이미지를 획득하려면, 카메라가 전송하는 이미지 데이터에 맞게 올바른 이미지 치수와 이미지 형식을 사용하도록 applet을 구성해야 합니다. 또 다른 예로는 애플리케이션 요구 사항에 맞게 applet에서 제공하는 트리거 모듈을 구성하는 것이 있습니다.

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

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에 추가되었습니다.

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

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

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

파라미터 유형#

파라미터에는 유형이 있으며, 파라미터의 값을 가져오거나 설정하려면 앱의 문서, VisualApplets을 사용하여 자체 설계한 앱에서 암시적으로, 또는 다음 함수를 사용하여 유형을 요청함으로써 유형을 알고 있어야 합니다. Fg_getParameterTypeById().

Parameter Type C/C++ Type
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

필드 파라미터 유형 중 하나를 가진 파라미터는 일반 C 사용 시 고려 사항(Considerations When Using Plain C) 챕터의 필드 파라미터 액세스(Accessing Field Parameters) 하위 섹션에 설명된 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

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

예를 들어, 이전 호출에서 얻은 프레임 그래버 핸들 fg 이(가) Fg_Init()에서 주어지면, 다음 코드는 앱의 첫 번째 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 채널 번호를 전달하여 이러한 파라미터의 각 인스턴스를 요청하거나 변경할 수 있습니다.

경우에 따라 마지막 파라미터가 다른 논리적 인덱스를 나타낼 수도 있습니다. 예를 들어 파라미터 FG_NR_OF_DMAS 또는 FG_NR_OF_CAMS 은(는) VisualApplets에서 정의된 스코프인 앱의 각 프로세스에 대해 여러 인스턴스로 존재합니다.

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

일부 파라미터는 획득한 이미지마다 다를 수 있으며 DMA 채널과 프레임 번호 또는 버퍼 번호가 모두 필요합니다. 이는 이미지가 컴퓨터 메모리로 전송되었을 때의 타임스탬프, 실제 이미지 데이터의 길이와 같은 모든 이미지 메타데이터 및 유사한 정보에 적용됩니다. 이러한 파라미터는 위에서 언급한 함수로 처리할 수 없으며, 이 주제에 대해서는 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을 사용하기 때문이며, 채널에 따라 파라미터 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 관리#

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

각 프레임 버퍼의 크기는 동일해야 하며, 일반적으로 너비 FG_WIDTH, 높이 FG_HEIGHT 및 Pixel Format FG_FORMAT에 의해 정의되는, 애플리케이션 요구 사항에 가장 큰 이미지를 저장할 수 있을 만큼 충분히 커야 합니다. (VisualApplets에서 설계된 앱릿의 경우 너비, 높이 및 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을 반환합니다.

반환된 포인터는 메모리 버퍼 자체에 대한 포인터가 아니므로 직접 사용해서는 안 됩니다! 메모리가 더 이상 필요하지 않으면 다음을 사용하여 해제해야 합니다. 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);
}

The 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() 을 사용하여 메모리 관리 구조체를 준비할 수 있습니다. 이 함수는 다음파 동일한 매개변수를 예상하지만 Fg_AllocMemEx(), 메모리를 할당하지는 않습니다. 애플리케이션에서 메모리를 할당한 후, 함수를 사용하여 각 프레임 버퍼를 개별적으로 추가해야 합니다. Fg_AddMem(). 애플리케이션이 취득 실행 중에 메모리 버퍼에 사용되는 프레임 버퍼의 동적 변경을 요구하는 경우 함수 Fg_DelMem() 을 사용하여 메모리 버퍼에서 프레임 버퍼를 제거할 수 있습니다. 메모리 버퍼가 더 이상 필요하지 않은 경우, 다음을 호출하여 관리 구조체를 먼저 해제해야 합니다. Fg_FreeMemHead() 그런 다음 프레임 버퍼용 메모리를 해제합니다.

다음 코드는 '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 이미지 데이터가 수신될 때 호출되도록 등록할 수 있습니다. 이 함수는 지정된 frame grabber 및 DMA 채널에 대해 등록되며, 호출 시 두 개의 파라미터가 전달됩니다. 콜백 함수의 첫 번째 파라미터는 ( ACQ_STANDARD 및 ACQ_SELECT) 또는 수신된 이미지의 버퍼 번호(, ACQ_BLOCK)입니다. 두 번째 파라미터는 호출 시 제공된 포인터로, Fg_registerApcHandlerEx() , 예를 들어 이미지 처리를 구현하는 클래스 인스턴스의 this 포인터와 같이 컨텍스트 구조체나 클래스에 대한 포인터로 사용할 수 있습니다.

특정 frame grabber의 각 DMA 채널에 대해 하나의 콜백 함수만 등록할 수 있습니다.

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

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

플래그 설명
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

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

  • 모든 단일 이미지가 콜백 함수로 전달됩니다.
  • 에러 값은 콜백 함수로 전달되지 않습니다.
  • 이미지 시간 제한이 발생하면 acquisition 루프가 종료됩니다.
  • 콜백 함수에서 0이 아닌 반환 값을 반환하면 acquisition 루프가 종료됩니다.
  • acquisition을 중지하면 acquisition 루프가 종료됩니다.
  • acquisition 루프는 기본 priority를 가진 스레드에서 실행됩니다.
  • 함수 Fg_getLastPicNumberBlockingEx() 함수가 호출되고, 그 결과가 콜백 함수로 전달됩니다.

정보

acquisition 루프가 종료되면 콜백 함수가 자동으로 등록 해제됩니다. acquisition이 중지될 때 항상 acquisition 루프를 종료하는 것이 논리적으로 보일 수 있지만, 반드시 그렇지는 않습니다. 예를 들어 응용 프로그램이 획득할 유한한 수의 프레임과 함께 Fg_AcquireEx를 호출하여 특정 수의 이미지 버스트로 acquisition을 실행해야 하는 경우를 생각해 보십시오. 프레임 수가 획득되면 드라이버에 의해 acquisition이 자동으로 중지됩니다. acquisition 루프를 계속 실행 상태로 유지하고 별도의 스레드에서 acquisition 버스트를 시작하는 것이 편리할 수 있습니다.

정보

설정 FG_APC_HIGH_PRIORITY 은 프로세스에 스레드 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++ 클래스 컨텍스트에서 콜백 함수를 사용하려면, 정적(static) 함수를 사용하여 콜백 핸들러를 등록하고, this 포인터를 컨텍스트 데이터 포인터로 사용하여 클래스 포인터로 다시 캐스팅한 후 그에 맞춰 사용할 수 있습니다.

더 이상 콜백 함수가 필요 없게 되면 다음을 호출하여 등록을 해제할 수 있습니다. Fg_unregisterApcHandler() 동일한 프레임 그래버 핸들과 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 관리 함수와 조합해서만 사용할 수 있으며 Fg_AllocMem() 및 Fg_FreeMem() 표준 취득 모델 사용으로 제한됩니다 ACQ_STANDARD. 이러한 함수의 사용은 권장되지 않으며 문서화되지 않습니다. 대신 함수 Fg_AcquireEx() 및 Fg_stopAcquireEx() 을(를) 사용해야 합니다.

Advanced 또는 Flexible Memory Management를 사용한 이미지 취득#
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 핸들에 연결하고 mem , 결과적으로 이미지 데이터 수신을 위해 할당된 Memory를 사용하게 됩니다.

취득은 매개변수로 지정된 프레임 수에 도달할 때까지 실행됩니다 frames 도달합니다. 만약 GRAB_INFINITE 전달되면 frames, 취득은 무한정 실행됩니다. 매개변수 flags, 취득 모델을 선택할 수 있습니다. 자세한 내용은 다음 섹션을 참조하십시오. Acquisition Models .

Model 설명
ACQ_STANDARD 프레임 버퍼 보호 기능이 없는 연속 취득
ACQ_BLOCK 프레임 버퍼 차단 기능이 있는 연속 취득
ACQ_SELECT 수동 프레임 버퍼 처리를 사용하는 완전한 애플리케이션 제어 취득

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

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

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

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

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

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() 을(를) 사용해야 합니다.

Advanced 또는 Flexible Memory Management를 사용하여 이미지 대기#
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 및 사용 중인 취득 모델에 따라 다릅니다. 오류가 발생할 경우 결과는 항상 음수 오류 코드가 됩니다. 다양한 전략에 대한 간략한 설명이 아래에 제공되지만, 일반적으로 해당 함수의 사용은 다음 섹션에 설명된 사용 사례로 제한되어야 합니다. The Blocking Acquisition Model. 그 외의 함수 사용은 권장되지 않으며 이 문서에서는 더 이상 자세히 다루지 않습니다.

SEL_NEW_IMAGE: 이 함수는 타임아웃 지정을 요구하며 적어도 하나의 새로운 이미지가 도착할 때까지 대기합니다. 이때 ACQ_STANDARD 및 ACQ_SELECT 가장 최신 이미지의 frame number가 반환됩니다. 이때 ACQ_BLOCK, 이 함수는 최신 이미지의 frame buffer를 블록하고 추가 이미지의 모든 frame buffer를 언블록한 다음, 블록된 이미지의 buffer number를 반환합니다.

SEL_NEXT_IMAGE: 이때 ACQ_STANDARD, 타임아웃이 지정되지 않은 경우 함수는 수신된 가장 최신 이미지의 buffer number를 반환합니다. 타임아웃이 지정된 경우 함수는 이전에 함수를 호출했을 때 수신된 마지막 프레임(함수를 이전에 호출하지 않은 경우 프레임 번호 1) 이후의 다음 프레임을 기다립니다. 함수는 수신된 가장 최신 이미지의 frame number를 반환합니다. 이때 ACQ_BLOCK, 이 함수는 아직 블록되거나 언블록되지 않은 수신된 첫 번째 이미지의 frame buffer를 블록하고 블록된 이미지의 buffer number를 반환합니다. 더 이상 이미지를 블록할 수 없고 타임아웃이 지정된 경우, 함수는 블록 작업을 수행하기 전에 적어도 하나의 새로운 이미지가 도착할 때까지 대기합니다.

SEL_ACT_IMAGE: 이때 ACQ_STANDARD, 이 함수는 다음과 같을 때와 동일하게 동작합니다. SEL_NEXT_IMAGE 가 지정됩니다. 이때 ACQ_BLOCK, 이 함수는 최신 이미지의 frame buffer를 블록하고 추가 이미지의 모든 frame buffer를 언블록한 다음, 블록된 이미지의 buffer number를 반환합니다. 더 이상 이미지를 블록할 수 없고 타임아웃이 지정된 경우, 함수는 블록 작업을 수행하기 전에 적어도 하나의 새로운 이미지가 도착할 때까지 대기합니다.

SEL_LAST_IMAGE: 이 함수는 해당 함수에 의해 또는 다음 함수에 의해 반환된 마지막 값을 반환합니다. Fg_getLastPicNumberBlockingEx(). 이것은 마지막으로 함수가 호출된 방식에 따라 마지막 frame number 또는 buffer number 중 하나입니다.

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(), 또는 비동기 모드에 대한 콜백 함수를 설정할 때 드라이버는 이미지 전송 인터럽트 처리 맥락에서 image acquisition도 추적합니다. 드라이버는 파라미터에 지정된 초 동안 이미지 데이터가 수신되지 않으면 image acquisition을 중지합니다. FG_TIMEOUT. 만약 FG_TIMEOUT 이 다음으로 설정된 경우 FG_TIMEOUT_INFINITE (값 FG_TIMEOUT_INFINITE 은(는) INT_MAX - 1) 드라이버는 두 이미지 수신 간의 시간 간격에 관계없이 acquisition을 중지하지 않습니다.

파라미터의 값 FG_TIMEOUT 은(는) acquisition이 시작될 때 드라이버로 전달됩니다. acquisition 시작 후 파라미터가 변경되더라도 acquisition이 중지되었다가 다시 시작될 때까지 드라이버에 반영되지 않습니다.

드라이버가 이미지 취득을 중지한 후, 이미지 대기 중이던 모든 함수 호출은 반환됩니다. FG_TIMEOUT_ERR 그리고 이미지 취득 중지 후에 이미지를 대기하기 위해 호출된 모든 함수는 반환됩니다. FG_TRANSFER_NOT_ACTIVE.

정보

파라미터의 기본값은 FG_TIMEOUT 은(는) 않습니다 FG_TIMEOUT_INFINITE, 대부분의 경우 1000000초(약 277시간 46분에 해당)로 설정됩니다. 이미지 취득을 시작하기 전에 FG_TIMEOUT 에서 FG_TIMEOUT_INFINITE 파라미터를 명시적으로 설정하는 것이 좋습니다.

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

Fg_setParameterWithType(fg, FG_TIMEOUT, FG_TIMEOUT_INFINITE, dma);

프레임 및 획득 정보#

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 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 Models 자세한 내용은 를 참조하세요.

다음 예제는 지정된 프레임에 대한 프레임 버퍼 포인터를 요청하는 방법을 보여줍니다.

// 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는 표준, 차단(blocking), 선택적(selective)의 세 가지 서로 다른 취득 모델을 제공하며, 이는 Fg_AcquireEx(): 표준, 차단(Blocking), 선택적(Selective). 이 세 가지 Acquisition 모델은 모두 장에서 설명한 Memory 모델을 기반으로 합니다. Memory 관리 이 모델은 이미지 획득을 위해 최소 두 개의 프레임 버퍼를 사용합니다.

이 장의 예제에서는 가상 메모리에서 연속적인 4개의 프레임 버퍼로 구성된 메모리 버퍼가 사용됩니다.

Memory Buffer Model

프레임 번호 및 버퍼 번호#

Framegrabber API 전반에서 프레임 번호와 버퍼 번호가 사용되며, 두 가지 모두 타입이 frameindex_t.

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

반면 버퍼 번호는 이미지 데이터가 상주하는 프레임 버퍼를 나타내며, N개의 버퍼에 대해 [1; N]범위에 속합니다. 여기서 사용된 예시에서 버퍼 번호는 1 ~ 4 사이이며 FB0 … FB3 에 해당합니다.

표준 Acquisition 모델(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(). 모든 프레임 버퍼는 이미지 데이터 획득을 위한 드라이버와 이미지 데이터 처리를 위한 응용 프로그램 모두에서 항상 액세스할 수 있습니다.

획득이 시작되면 드라이버는 첫 번째 프레임 버퍼부터 시작하여 이미지 데이터 전송을 위해 프레임 grabber에 하나 이상의 프레임 버퍼를 대기열에 넣습니다. FB0. 이미지가 컴퓨터 Memory에 완전히 전송되면 소프트웨어에 전송 완료가 통지되고, 드라이버는 하나의 프레임 버퍼를 추가로 대기열에 넣습니다. 프레임 grabber는 큐의 다음 버퍼(예시에서는 FB1.

(대기열에 대기하는 프레임 버퍼의 수는 사용된 프레임 grabber, 드라이버 버전, Windows 레지스트리의 설정 또는 Linux 드라이버의 파라미터 등 다양한 요인에 따라 달라집니다. 그러나 표준 획득 모델에서는 대기열 처리가 항상 선형 방식으로 이루어지며, 마지막 프레임 버퍼가 대기열에 들어간 후 FB0 부터 다시 시작됩니다. 대기 중인 버퍼의 수는 컴퓨터에서 달성할 수 있는 최대 프레임 레이트에 영향을 미칠 수 있지만, 이 영향은 초당 ~10,000프레임 이상에서만 측정 가능합니다.)

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

표준 획득 모델에서는 이미지 획득이 이미지 처리를 "초과"하지 않도록 보장하는 전적인 책임이 응용 프로그램에 있습니다. 이는 이미지 소스 트리거링이 이미지 처리와 결합되어 응용 프로그램에서 제어되거나, 버퍼 수가 사용된 컴퓨터 시스템의 프레임 레이트 및 성능에 맞게 신중하게 조정되거나, 이미지를 건너뛸 수 있는 경우에만 보장될 수 있습니다.

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

응용 프로그램 측의 제어 없이 이미지가 연속적으로 생성되는 시나리오에서는 이미지 소스와 드라이버의 버퍼 처리 모두 프리런(free running) 상태인 것으로 간주할 수 있습니다. 다음 예시에서 FB0 및 FB1 은(는) 유효한 이미지 데이터를 포함합니다. FB0 이(가) 응용 프로그램에 의해 처리되고 있으며, FB1 은(는) 처리가 대기 중입니다. 드라이버가 최소한 FB2 을(를) 대기열에 넣었으며 현재 이미지 데이터가 전송 중입니다. FB3 이미 대기열에 들어갔을 수 있더라도 아직 사용되고 있지 않으므로 이 상황은 여전히 안전합니다.

Memory Buffer Model Safe

함수 호출 Fg_getLastPicNumberBlockingEx() 처리가 완료된 후 다음 프레임 번호에 대해 FB0 이 경우 전송이 완료되지 않은 경우 단일 새 프레임( FB1로 전송된 이미지의 프레임 번호)을 반환합니다. FB2 그 사이에 완료됩니다.

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

Memory Buffer Model Unsafe

함수 호출 Fg_getLastPicNumberBlockingEx() 처리가 완료된 후 다음 프레임 번호에 대해 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 ...
    }
}

응용 프로그램이 이미지를 건너뛸 수 있고 수신된 가장 최신 프레임만 처리해야 하는 경우, 내부 for 루프를 취득 루프에서 제외하고 대신 다음만 처리할 수 있습니다. 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 전달되지 않았습니다.

차단 Acquisition 모델(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에서 변경되었습니다.

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

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

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

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

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

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

위의 목록은 완전하지 않으며, blocking acquisition 모델과 관련된 전략만 포함하고 있습니다.

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

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

함수 Fg_getStatusEx() 의 버퍼 번호를 전달할 수 있으며, 이를 통해 blocking acquisition 모델과 관련된 다음 상태 정보를 요청할 수 있습니다.

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() 결과가 발생할 수 있으며, 획득 루프에서 전달된 페이지만 카운트하는 경우 문제가 될 수 있습니다.

이전 이미지의 처리가 아직 끝나지 않은 상태에서 애플리케이션이 단일 이미지만 트리거하는 시나리오에서는, 처리 중인 이미지 데이터를 위한 버퍼와 이미지 데이터를 전송할 버퍼 등 최소 두 개의 버퍼가 필요합니다. (버퍼 잠금(locking)이 발생하므로, 애플리케이션이 이미지 처리가 완전히 끝난 후에만 트리거가 생성되도록 보장하더라도 모든 경우에 최소 두 개의 버퍼가 필요합니다.)

애플리케이션 측의 제어 없이 이미지가 지속적으로 생성되는 시나리오에서는 이미지 소스가 프리런닝(free running) 상태인 것으로 간주할 수 있습니다. 그러나 드라이버는 차단되지 않은 사용 가능한 버퍼가 있는 동안에만 애플리케이션에 이미지를 전달할 수 있습니다. 다음 예시에서, 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 전달되지 않았습니다.

선택적 취득 모델 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 하위 섹션에서 언급했듯이, 프레임 그래버에 대기열로 추가되는 프레임 버퍼의 수는 다양한 요인에 따라 달라집니다.)

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

함수 Fg_setStatusEx() 을(를) 호출하여 다음을 사용하여 프레임 버퍼를 선택할 수 있습니다. FG_SELECT_BUFFER 그리고 버퍼 번호를 전달합니다.

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

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

Memory Buffer Model Safe

함수 호출 Fg_getLastPicNumberBlockingEx() 처리가 완료된 후 다음 프레임 번호에 대해 FB0 이 경우 전송이 완료되지 않은 경우 단일 새 프레임( FB1로 전송된 이미지의 프레임 번호)을 반환합니다. FB2 그 사이에 완료됩니다.

이미지 처리가 이미지 취득보다 느린 경우, 애플리케이션은 처리를 완료했을 수 있습니다. FB0, 이를 선택하고 처리 단계로 넘어갔습니다. FB1. 그러나 다음 예에서는 그 사이에 두 개의 이미지가 더 전송되었으며, FB2 및 FB3, 드라이버가 다시 시작되었습니다. FB0. 이미지 전송이 완료되었을 때, 애플리케이션이 처리를 완료하지 못했다면 FB1 하고 이를 선택하면, 드라이버에는 대기열에 넣을 수 있는 빈 버퍼가 더 이상 남지 않게 됩니다. 새로운 이미지가 더 이상 도착하지 않는 한, 이 상황은 다음과 같은 상황에서 발생할 수 있는 암묵적인 이미지 손실을 유발하지 않습니다. ACQ_BLOCK. 그러나 다른 이미지가 수신되는 즉시 프레임 래버의 내부 Memory 버퍼에 오버플로우가 발생하여 데이터 손실이 발생할 수 있습니다.

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 전달되지 않았습니다.

Frame Grabber로 데이터 전송#

제한 사항

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

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

VisualApplets 연산자 DmaFromPC을(를) 사용하면 PC에서 프레임 래버로 데이터를 전송할 수 있습니다. 활용 사례로는 이미지 데이터 공동 처리 또는 프레임 래버에서의 복잡한 이미지 처리를 위한 추가 파라미터 제공 등이 이에 국한되지 않고 포함됩니다.

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);
}

또는 유연한 메모리 관리에 설명된 함수를 사용할 수 있습니다. 예:

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);
}

버퍼의 크기는 모두 동일하지만, 단일 전송당 바이트 수는 개별적으로 지정됩니다. 데이터 전송 크기는 연산자의 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 핸들에 연결하고 mem 따라서 데이터 전송을 위해 할당된 Memory를 사용합니다.

함수에 전달되는 dma Parameter는 Fg_startBufferQueue() VisualApplets 디자인에 있는 VisualApplets operator를 사용하여 PC로 이미지 전송을 수행하는 일반 DMA 채널의 수에 따라 결정됩니다. VisualApplets operator의 DMA 채널은 DmaToPC 항상 마지막 DMA 채널입니다. DmaFromPC 모든 데이터 전송이 완료된 후

을(를) 호출하면 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 Parameter는 NULL.

버퍼 전송 완료 대기#

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

함수 Fg_waitForBuffers() 선택 사항이며 timeout 매개변수에 지정된 특정 DMA 채널에서 dmaParameter에 지정된 초 내에 적어도 하나의 버퍼가 완전히 전송될 때까지 대기합니다. 성공 시 완전히 전송된 버퍼의 수를 반환하며, 실패 시 음수 오류 코드를 반환합니다.

을(를) 사용하여 큐에 추가되었던 Fg_queueBuffer() 버퍼만 재사용할 수 있으며, 버퍼가 완전히 전송된 후 새 데이터를 Fill할 수 있습니다.

VisualApplets operator의 DmaFromPC 다음과 매우 유사함 선택적 취득 모델. 즉, 애플리케이션이 버퍼 사용을 완전히 제어하므로 버퍼 번호를 추적하는 것 역시 애플리케이션의 책임입니다. 버퍼가 항상 동일한 순서로 선택되지 않는 한, 전송 Counter를 버퍼 번호로 변환하는 단순한 방법은 없습니다. 또한 변환을 수행하는 API 함수도 존재하지 않습니다.

Applet 이벤트#

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

각 이벤트 소스는 고유한 이름을 가지며 이벤트 마스크라고 하는 부호 없는 64비트 정수의 단일 비트로 식별됩니다. 이를 통해 예를 들어 여러 이벤트 소스의 여러 이벤트 마스크에 대해 이진 OR operator | 를 사용하여 여러 이벤트 소스를 함께 그룹화할 수 있습니다. 그러나 이는 또한 어떤 Applet이든 최대 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 이상의 값을 반환하고, 그렇지 않으면 음수 에러 코드를 반환합니다.

모든 이벤트 소스를 반복(iterate)하려면 다음 함수를 사용할 수 있습니다. 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 은(는) 이벤트 소스 그룹에서 하나 이상의 이벤트가 수신될 때 콜백되도록 등록할 수 있습니다. 이 함수는 특정 프레임 그래버와 이벤트 마스크에 대해 등록되며 호출 시 세 개의 파라미터가 전달됩니다. 콜백 함수의 첫 번째 파라미터는 이벤트가 수신된 모든 이벤트 소스의 이벤트 마스크입니다. 두 번째 파라미터는 Fg_registerEventCallback() , 예를 들어 이미지 처리를 구현하는 클래스 인스턴스의 this 호출 시 제공된 포인터이며, 이미지 처리를 구현하는 클래스 인스턴스의 포인터입니다. 세 번째 파라미터는 struct fg_event_info 에 대한 포인터로, 애플리케이션에서 할당하여 Fg_registerEventCallback() 호출 시 전달해야 하며 이벤트에 대한 정보를 저장하는 데 사용됩니다.

특정 프레임 그래버의 동일한 이벤트 그룹에 대해 하나의 콜백 함수만 등록할 수 있습니다.

콜백 함수는 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++ 클래스 컨텍스트에서 콜백 함수를 사용하려면, 정적(static) 함수를 사용하여 콜백 핸들러를 등록하고, 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().

여러 프로세스에서의 Frame Grabber 사용 지원#

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

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

마스터/슬레이브 모드의 한 가지 특수한 제한 사항은 두 프로세스가 프레임 grabber의 동일한 기능을 제어하려고 할 때마다 마지막 프로세스가 "우선시되어" 첫 번째 프로세스의 작업을 덮어쓴다는 점입니다. 첫 번째 프로세스는 덮어쓰여진 사실조차 알아차리지 못한 채 프레임 grabber의 상태에 대해 잘못된 가정을 할 수 있습니다. (프로세스 간 통신을 사용하여 프로세스 간 상태를 동기화하는 실험적 기능이 존재하지만, 이 접근 방식에는 고유한 영향이 따르며 파라미터 및 취득 동기화에 대한 실험적 지원 섹션에서 다룰 것입니다.)

일반적인 권장 사항은 프로세스가 고유한 작업(애플릿 파라미터 및 Property과 관련하여 작업이 서로 겹치지 않음)을 수행하고 다른 프로세스의 존재를 알 필요가 없도록 프로세스를 설계하는 것입니다. 한 가지 예외는 애플릿의 읽기 전용 Property에만 액세스하거나 프로세스 간 통신 수단을 통해 다른 프로세스에서 정보를 수집하는 모니터링 프로세스입니다.

또 다른 제한 사항은 마스터 프로세스만 프레임 그래버를 완전히 초기화하는 반면, 각 프로세스에서 기본 초기화가 수행되어야 한다는 점입니다. 이 기본 초기화는 이전 프로세스가 이미 이미지 수집이나 카메라 검색을 시작한 경우 이를 방해할 수 있습니다.

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

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:

플래그 설명
FG_INIT_LIBRARIES_SINGLE 기본 초기화, 동기화 없음
FG_INIT_LIBRARIES_MASTER 마스터 초기화, 슬레이브 동기화 준비
FG_INIT_LIBRARIES_SLAVE 슬레이브 초기화, 마스터 대기
FG_INIT_LIBRARIES_SEQUENTIAL 엄격한 순차적 시작
FG_INIT_LIBRARIES_AUTOSTART_ON_INIT 프레임 grabber 초기화 시 다음 슬레이브 시작
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() 는(은) 슬레이브 프로세스에서 사용될 때 FG_INIT_LIBRARIES_SEQUENTIAL 을(를) 사용해야 하며 슬레이브 프로세스의 우선순위를 정의합니다. 가장 높은 우선순위는 1이고 가장 낮은 우선순위는 63입니다. 그룹의 각 프로세스는 고유한 우선순위를 가져야 하며, 우선순위는 간격이 생기지 않도록 할당되어야 합니다. (프로세스 2가 프로세스 3을 시작하려고 하지만 프로세스 3이 없으면 아무도 프로세스 4를 시작하지 않습니다.) 매크로 FG_INIT_LIBRARIES_SET_NUMBER_OF_SLAVES() 은(는) 마스터 프로세스에서 사용될 때 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에서 지원되지 않습니다.

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

정보

파라미터 및 취득 동기화에 대한 실험적 지원은 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(Non-Uniform Memory Access)를 사용하는 다중 프로세서 컴퓨터에서는 각 물리적 프로세서가 자체 메모리 및 주변 장치 버스를 가집니다. 프로세스가 실행 중인 동일한 물리적 프로세서의 리소스만 액세스하는 한, 단일 프로세서 컴퓨터만큼 빠르고 대칭형 멀티프로세싱(SMP)을 사용하는 다중 프로세서 컴퓨터보다 훨씬 빠릅니다. 그러나 한 물리적 프로세서에서 실행 중인 프로세스가 다른 물리적 프로세서에 속한 리소스에 액세스하려는 경우 데이터가 두 물리적 프로세서 사이를 이동해야 하므로 액세스가 느려집니다. 자세한 내용은 위키백과의 비균일 기억 장치 접근(Non-Uniform Memory Access) 문서를 참조하십시오.

NUMA 컴퓨터에서 실행되는 애플리케이션을 지원하려면, 프레임 그래버에 접근하는 모든 스레드는 해당 장치가 로컬로 연결된 물리적 프로세서에 고정(pin)되어야 합니다. 이는 다음을 호출하여 수행할 수 있습니다. 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가 편의성이나 타입 안전성을 위해 제공하는 일부 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.

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

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 파라미터 작업, 가장 일반적인 유형의 파라미터 속성을 요청하는 C++ 래퍼가 문서화되어 있습니다. 일반 C에서 파라미터 속성에 액세스하거나 C++ 래퍼가 존재하지 않는 유형의 파라미터 속성에 액세스하려면 다음 함수를 사용합니다. 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 값 파라미터 속성 액세스#
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가 열거형 파라미터라고 가정할 때 파라미터의 열거형 값 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을 전달해야 합니다. 대신 취득 루프를 제어하는 플래그는 멤버에 전달됩니다. 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++ 클래스 컨텍스트에서 콜백 함수를 사용하려면, 정적(static) 함수를 사용하여 콜백 핸들러를 등록하고, this 포인터를 컨텍스트 데이터 포인터로 사용하여 클래스 포인터로 다시 캐스팅한 후 그에 맞춰 사용할 수 있습니다.

더 이상 콜백 함수가 필요 없게 되면 다음을 호출하여 등록을 해제할 수 있습니다. Fg_registerApcHandler() 동일한 프레임 그래버 핸들과 DMA 채널을 사용하되 다음을 전달합니다. 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() 사용 중인 획득 모델에 관계없이 획득 루프 내에서 사용했습니다. 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() 콜백 핸들러에서 호출하는 것은 권장되지 않으며, 애플리케이션 코드의 하위 호환성이 절대적으로 필요한 경우에만 사용해야 합니다. ↩↩