주요 콘텐츠

이 페이지는 기계 번역을 사용하여 번역되었습니다. 최신 내용을 영문으로 보려면 여기를 클릭하십시오.

라이브 이미지 수집을 위한 앱 만들기

이 예제에서는 앱 디자이너에서 사용 가능한 모든 카메라를 검색하고 선택한 카메라의 사용자 지정 라이브 미리 보기를 표시하는 앱을 만드는 방법을 보여줍니다. 또한, 이 예제에서는 앱을 사용하여 카메라 속성을 구성하고, 미리보기를 설정 및 구성하고, 이미지와 비디오를 디스크에 저장하는 방법을 보여줍니다.

앱을 실행하는 데 필요한 것:

  • Image Acquisition Toolbox™

  • 다음 어댑터 중 하나: winvideo, macvideo, linuxvideo(Image Acquisition Toolbox Support Package for OS Generic Video Interface), gentl(Image Acquisition Toolbox GenICam™ 인터페이스 지원 패키지), gige(Image Acquisition Toolbox Support Package for GigE Vision Hardware). 다른 어댑터도 약간만 수정하면 작동할 수 있습니다.

  • 설치된 어댑터 중 하나로 지원되는 카메라

앱 레이아웃 디자인

디자인 보기를 사용하여 앱 디자이너에서 앱 레이아웃을 구성하고 앱 목표에 따라 사용자에게 컨트롤을 제공합니다. 이 경우 사용자가 다음을 수행할 수 있도록 앱을 구성하세요.

  • 사용 가능한 카메라 목록을 만들고 유지관리합니다.

  • 카메라에 연결하고 분리합니다.

  • 카메라 속성을 설정합니다.

  • 실시간 미리보기를 받고 표시 방법을 구성하세요.

이러한 기능을 구성하기 위해 앱 레이아웃에는 카메라 연결, 카메라 속성, 미리보기 속성, 기록, 라이브 미리보기 표시 등의 다양한 패널이 포함되어 있습니다.

카메라 목록 만들기 및 유지 관리

연결된 카메라 목록을 가져오고 카메라 선택 드롭다운 항목을 채우는 앱 도우미 함수 refreshCameraList를 만듭니다.

function refreshCameraList(app)
    updateDeviceTable(app);
    deviceList = strcat(app.DeviceTable(:,:).Name, '-', app.DeviceTable(:,:).Adaptor);
    app.CameraDropDown.Items = deviceList;
    app.FormatDropDown.Items = imaqhwinfo(app.DeviceTable(1,:).Adaptor{1}).DeviceInfo.SupportedFormats;
end

카메라 목록을 유지 관리하기 위해 updateDeviceTable 도우미 함수는 imaqhwinfo 함수를 사용하고 설치된 어댑터를 통해 연결된 모든 장치를 가져옵니다. 이 함수는 어댑터 이름, 해당 어댑터 내의 장치 인덱스, 장치 이름을 포함하는 표에 카메라 정보를 저장합니다.

function updateDeviceTable(app)
    % Create the device table with all recognized devices
    app.DeviceTable = table;

    % Get a list of all the installed adaptors
    adaptors = imaqhwinfo().InstalledAdaptors;

    % Iterate over every element in an array
    for adaptor = adaptors % Step through each adaptor
        devices = imaqhwinfo(cell2mat(adaptor)).DeviceInfo; % get all devices for adaptor
        for ii = 1:size(devices,2)
            % Add the device to the device table
            app.DeviceTable = [app.DeviceTable; {string(adaptor), ii, string(devices(ii).DeviceName)}];
        end
    end

    % Set the table column names for easy access in the future
    app.DeviceTable.Properties.VariableNames = ["Adaptor", "Number", "Name"];
end

앱이 시작되면 startupFcnrefreshCameraList를 실행하여 앱의 카메라 목록을 업데이트합니다.

function startupFcn(app)
    ...
    refreshCameraList(app)
    ...
end

카메라에 연결

앱 사용자가 연결버튼을 클릭하면 선택한 카메라를 기반으로 videoinput 객체가 생성됩니다. 다른 앱 함수가 videoinput 객체에 액세스할 수 있도록 하려면 앱 속성인 app.VideoObject에 저장합니다.

function ConnectButtonPushed(app, event)
    ...
    app.VideoObject = videoinput(string(selectedCamera.Adaptor), selectedCamera.Number, app.FormatDropDown.Value);
    ...
end

카메라 연결을 끊으려면 videoinput delete 함수를 실행하세요. 앱 속성을 사용하여 videoinput 객체에 액세스합니다.

function DisconnectButtonPushed(app, event)
    stoppreview(app.VideoObject);
    delete(app.VideoObject);
    ...
end

카메라 속성 구성

카메라는 구성 가능한 속성을 다양하게 가질 수 있습니다. 하지만 앱 사용자는 몇 가지 속성만 조정하고 싶어할 수도 있습니다. setupPropUIComponents 도우미 함수는 사용자가 지정한 카메라 속성에 대한 UI 구성 요소를 프로그래밍 방식으로 생성합니다. 구체적으로, 각 숫자형 카메라 속성에 대한 슬라이더와 숫자형 편집 필드를 생성하고, 열거형인 각 카메라 속성에 대한 드롭다운을 생성합니다.

앱 사용자가 UI 구성 요소 속성 값을 변경하면 구성 요소 콜백 함수에서 카메라 속성 값을 업데이트합니다. 지정된 값이 카메라에서 지원되지 않으면 카메라는 대신 지원되는 값으로 속성을 조정합니다. 업데이트된 카메라 속성 값과 동기화 상태를 유지하려면 UI 구성 요소를 새로 고칩니다.

UI 구성 요소태그객체 식별자와 findobj 함수는 업데이트되는 카메라 속성과 연관된 UI 구성 요소를 찾습니다.

function sliderChangedFcn(app, src, event)
    app.CameraSource.(src.Tag) = event.Value;
    
    actualValue = app.CameraSource.(src.Tag);
    src.Value = double(actualValue);

    editField = findobj(app.PropertiesLayout,'Tag',src.Tag + "Edit");
    editField.Value = double(actualValue);
end

미리보기

캡처한 이미지를 라이브로 표시하기 전에 사용자 정의 미리보기 콜백을 사용하여 처리합니다. 또한, 고해상도 카메라의 경우 MaxRenderedResolution 이미지 속성을 사용하여 더 낮은 화면 미리보기 해상도를 사용하여 미리보기 성능을 개선합니다.

function refreshPreview(app)
    ...
    app.ImagePreview = image(app.imageAxes,zeros(resolution(2), resolution(1), nBands, imaqinfo.NativeDataType));
    ...
    app.ImagePreview.MaxRenderedResolution = 1920;
    ...
    setappdata(app.ImagePreview,'UpdatePreviewWindowFcn',@(obj,event,hImage) previewCallback(app,obj,event,hImage))
    ...
    preview(app.VideoObject,app.ImagePreview);
end

이 예제에서는 fliplr 함수를 사용하여 이미지를 미러링합니다.

function previewCallback(app,obj,event,hImage)
    cdata = event.Data;
    if app.MirrorSwitch.Value == "On"
        cdata = fliplr(cdata);
    end
    hImage.CData = cdata;
end

비광학 카메라는 흑백 형식(강도 이미지)으로 데이터를 반환할 수 있습니다. 예를 들어, 열 적외선 카메라는 온도 이미지 데이터를 반환합니다. 이러한 유형의 애플리케이션에서 데이터를 효과적으로 시각화하려면 회색조가 아닌 색상맵을 적용하고 색상 제한을 설정합니다. 또한, 8비트보다 큰 비트 심도의 형식을 사용하는 경우 전체 데이터 범위를 적절하게 시각화할 수 있도록 PreviewFullBitDepth 속성을 설정해야 합니다.

function adjustPreviewBands(app)
    nBands = app.VideoObject.NumberOfBands;

    % Check for grayscale/scientific formats
    if(nBands == 1)
        app.VideoObject.PreviewFullBitDepth = "on";
        ...
        app.ImagePreview.CDataMapping = 'scaled';
        app.ImagePreview.Parent.CLimMode = 'auto';
        ...
    end
end
function ColormapDropDownValueChanged(app, event)
    value = app.ColormapDropDown.Value;
    colormap(app.ImagePreview.Parent,value);
end

이미지와 비디오를 디스크에 저장

이미지를 디스크에 저장하려면 videoinput getsnapshot를 호출하여 이미지를 가져오고 imwrite 함수를 사용합니다.

function SnapshotButtonPushed(app, event)
    img = getsnapshot(app.VideoObject);
    ...
    imwrite(img,fileName);
    ...
end

비디오를 디스크에 저장하려면 내장된 videoinput DiskLogger 기능을 사용하세요.

function RecordButtonPushed(app, event)
    ...
    logfile = VideoWriter(fileName, format);
    app.VideoObject.DiskLogger = logfile;
    ... 
    start(app.VideoObject)
end

오류 처리

명령 창 대신 앱에서 알림으로 오류를 표시할 수 있습니다. try/catch를 사용한 오류 처리법 블록과 uialert 함수를 사용하세요.

function ConnectButtonPushed(app, event)
    ...
    try
        app.VideoObject = videoinput(string(selectedCamera.Adaptor), selectedCamera.Number, app.FormatDropDown.Value);
    catch E
        uialert(app.UIFigure,E.message, "Camera Object Creation Error");
        return
    end
    ...
end

앱 사용자 지정 및 실행

카메라와 함께 이 앱을 실행하려면 앱을 사용할 때 구성하려는 카메라 속성을 사용자 지정하세요.

앱 속성으로 정의된 CameraProperties 구조체에서 속성을 지정할 수 있습니다. 사용 가능한 속성은 videoinput 어댑터와 카메라에 따라 달라집니다. 이 예제 앱은 숫자형 속성과 열거형 속성을 모두 지원합니다.

properties (Access = private)
    ...
    CameraProperties = struct( ...
        winvideo = ["Exposure", "ExposureMode", "FrameRate"], ...
        gentl = ["AcquisitionFrameRate", "AcquisitionFrameRateEnable", "ExposureTime", "ExposureAuto"], ...
        gige = ["AcquisitionFrameRate", "AcquisitionFrameRateEnable", "ExposureTime", "ExposureAuto"], ...
        demo = string.empty, ...
        macvideo = string.empty, ...
        linuxvideo = string.empty)
    ...
end

일부 카메라 속성은 상호 종속적입니다(예: ExposureExposureMode). CameraPropertiesDict 앱 속성에서 종속 속성을 정의할 수 있습니다. 이 속성은 각 videoinput 어댑터에 대한 dictionary 필드가 포함된 구조체입니다. 사전의 키는 제어 속성이고 값은 종속 속성입니다.

properties (Access = private)
    ...
    CameraPropertiesDict = struct( ...
        winvideo=dictionary(ExposureMode="Exposure"), ...
        gentl=dictionary( ...
            AcquisitionFrameRateEnable="AcquisitionFrameRate", ...
            ExposureAuto="ExposureTime"), ...
        gige=dictionary( ...
            AcquisitionFrameRateEnable="AcquisitionFrameRate", ...
            ExposureAuto="ExposureTime"), ...
        demo = dictionary(), ...
        macvideo = dictionary(), ...
        linuxvideo = dictionary())
    ...
end

앱 속성 DisablePropStrings는 페어링된 종속 속성과 연관된 UI 구성 요소의 상태(활성화/비활성화)를 제어하는 값을 정의합니다. 예를 들어, ExposureExposureMode는 쌍을 이룹니다. 노출 슬라이더와 숫자 편집 필드를 활성화하려면 ExposureModemanual로 설정해야 합니다.

properties (Access = private)
    ...
    DisablePropStrings = struct( ...
        winvideo="manual", ...
        gentl=["True", "Off"], ...
        gige=["True", "Off"], ...
        demo = [], ...
        macvideo = [], ...
        linuxvideo = [])
    ...
end

참고 항목