C# 바코드 스캐너를 사용하여 책 스캔

블로그 카테고리: 바코드.NET

2025/06/09

바코드 스캐너를 사용한 책 스캔은 도서관, 서점, 기록 보관소 및 교육 기관의 자동화에 필수적인 부분이 되고 있습니다. 이 접근 방식은 대규모 컬렉션의 처리 속도를 높이고 회계 오류를 최소화하며 책과 독자 간의 새로운 상호 작용 방식을 제공합니다.



도서용 소프트웨어 바코드 스캐너의 작동 원리

소프트웨어 스캐너는 카메라, 스캐너 또는 모바일 장치를 사용하여 책에 부착된 바코드를 자동으로 인식하고 해독하는 특수 소프트웨어 솔루션입니다. 이를 구현하면 수동 데이터 입력 없이 빠르고 정확한 전자 회계, 자금 관리 및 거래 처리를 수행할 수 있습니다.

소프트웨어 스캐너의 작동 원리는 다음과 같습니다. 장치(예: 카메라 또는 스캐너)가 책 표지나 페이지에서 바코드 이미지를 읽으면 소프트웨어가 바코드에 인코딩된 정보(예: ISBN)를 해독하여 이 데이터를 추가 처리를 위해 도서관 또는 유통 시스템으로 전송합니다.

도서의 바코드

최근 수십 년 동안 출판된 대부분의 책에는 바코드가 있습니다. 일반적으로 EAN-13 형식의 ISBN(국제 표준 도서 번호) 또는 QR 코드(차세대)입니다. (출판물). 책에 대한 고유 식별자와 함께 발행에 대한 추가 정보가 포함되는 경우가 많습니다.

카메라 및 스캐너 사용

소프트웨어 바코드 스캐너는 특수 장비(스캐너, 터미널)와 웹캠 또는 모바일 장치를 모두 사용하여 바코드를 인식할 수 있는 애플리케이션 또는 라이브러리로, 프로세스를 최대한 모바일화하고 접근성을 높입니다.

인식 및 데이터 처리

이미지 처리 알고리즘은 책에서 바코드를 찾아 바코드에 포함된 정보를 해독하고 카탈로그, 데이터베이스 및 도서관 시스템과 통합하여 빠르고 정확한 회계 처리를 보장합니다.



도서 스캔 단계

소프트웨어 바코드 스캐너를 사용한 도서 스캔은 여러 단계로 구성되며, 각 단계는 도서 대출 및 반납, 회계 처리의 정확성과 효율성에 매우 중요합니다. 적절하게 구성된 작업 주기는 재고 조사 시간을 크게 단축하고 데이터 품질을 향상시키며 도서관 서비스를 최적화할 수 있습니다. 서점.

장비 및 소프트웨어 준비

스캔을 시작하기 전에 사용 중인 장치가 선택한 소프트웨어 및 바코드 표준을 지원하는지 확인해야 합니다. 그런 다음:

바코드 스캔 및 인식

이 단계에서 책에서 바코드를 실제로 읽습니다.
바코드가 카메라 또는 스캐너에 명확하게 보이도록 책을 배치합니다.

도서관 또는 거래 시스템과의 통합

인식에 성공하면 소프트웨어 스캐너가 수신된 데이터를 정보 시스템으로 자동으로 전송합니다.

데이터 저장, 분석 및 후속 작업

데이터베이스에 정보가 저장되면 회계 및 분석 프로세스를 자동화할 수 있는 기회가 열립니다.



최신 소프트웨어 스캐너의 기술적 특징 및 장점

최신 소프트웨어 바코드 스캐너는 다음과 같은 기술 솔루션을 제공합니다.

최신 바코드 스캐너 소프트웨어는 자동화, 회계 투명성 및 서비스 속도 향상을 추구하는 모든 도서관이나 서점에 필수적인 도구입니다. 이러한 소프트웨어를 통해 종이 자료 처리는 최소한의 비용으로 최대한의 효과를 내면서 현대적인 디지털 수준으로 전환됩니다.

소프트웨어 솔루션 선택

도서용 바코드 스캐너 소프트웨어를 선택할 때는 다음 사항을 고려하는 것이 좋습니다.

범용 솔루션은 IT 인프라에 쉽게 통합되고 데스크톱 PC부터 모바일폰까지 다양한 기기에서 작동을 지원해야 합니다. 간단한 인터페이스, 업데이트 기능 및 기술 지원을 제공하는 제품을 선택하는 것이 좋습니다.

발전 전망

소프트웨어 바코드 스캐너를 이용한 도서 스캔 기술은 빠르게 발전하고 있습니다. 가까운 미래에는 데이터매트릭스(DataMatrix)나 QR 코드와 같은 2D 바코드가 더욱 널리 사용될 것으로 예상됩니다. 2D 바코드는 전자책 링크, 주석, 보안 식별자 등 더 많은 정보를 담을 수 있기 때문입니다.

스캐너와 클라우드 서비스 및 디지털 도서관의 통합이 증가하고 있으며, 이를 통해 온라인 자료에 대한 자동 접근과 사용자 서비스 확장이 가능해질 것입니다. 향후에는 도서 상태 자동 분석, 추천 도서 생성, 도서관 자료 이동에 대한 종합적인 분석 및 모니터링과 같은 지능형 기능의 도입도 기대됩니다.

결론

바코드 스캔 소프트웨어 솔루션을 선택할 때는 지원되는 형식, 속도, 통합 기능, 사용 편의성 등 여러 요소를 신중하게 고려해야 합니다. 기술 발전 전망은 자동화에 새로운 가능성을 열어주며, 도서관 시스템의 효율성을 높이고 사용자 서비스를 개선할 것입니다.

VintaSoft Barcode .NET SDK 개발사인 VintaSoft는 도서관 바코드 시스템 구축을 크게 간소화할 수 있습니다. 이 강력한 도구는 다양한 형식의 바코드를 지원하고, 높은 스캔 속도와 정확도를 제공하며, 기존 도서관 시스템과 쉽게 통합됩니다. VintaSoft Barcode .NET SDK를 통해 도서관은 회계 및 도서 서비스와 관련된 모든 프로세스를 신속하고 효율적으로 자동화하여 서비스 품질을 향상시키고 상당한 자원 절감 효과를 얻을 수 있습니다.


다음은 카메라로 캡처한 이미지에서 ISBN 바코드를 인식하는 방법을 보여주는 C# 코드입니다.
/// <summary>
/// Reads barcode from a <see cref="System.Drawing.Bitmap"/>.
/// </summary>
/// <param name="bitmap">A bitmap with barcodes.</param>
public static void ReadIsbnBarcodesFromBitmap(System.Drawing.Bitmap bitmap)
{
    // create barcode reader
    using (Vintasoft.Barcode.BarcodeReader reader = new Vintasoft.Barcode.BarcodeReader())
    {
        // specify that reader must search for ISBN barcodes
        reader.Settings.ScanBarcodeTypes = Vintasoft.Barcode.BarcodeType.ISBN;

        // read barcodes from image
        Vintasoft.Barcode.IBarcodeInfo[] infos = Vintasoft.Barcode.GdiExtensions.ReadBarcodes(reader, bitmap);

        // if barcodes are not detected
        if (infos.Length == 0)
        {
            System.Console.WriteLine("No barcodes found.");
        }
        // if barcodes are detected
        else
        {
            // get information about extracted barcodes

            System.Console.WriteLine(string.Format("{0} barcodes found:", infos.Length));
            System.Console.WriteLine();
            for (int i = 0; i < infos.Length; i++)
            {
                Vintasoft.Barcode.IBarcodeInfo info = infos[i];
                System.Console.WriteLine(string.Format("[{0}:{1}]", i + 1, info.BarcodeType));
                System.Console.WriteLine(string.Format("Value:      {0}", info.Value));
                System.Console.WriteLine(string.Format("Region:     {0}", info.Region));
                System.Console.WriteLine();
            }
        }
    }
}



다음은 DirectShow 카메라(VintaSoft Imaging .NET SDK)에서 이미지를 캡처하고 WinForms 애플리케이션에서 캡처된 이미지(VintaSoft Barcode .NET SDK)에서 ISBN 바코드를 인식하는 방법을 보여주는 C# 코드입니다.
public partial class IsbnBarcodeScannerForm : Form
{
    /// <summary>
    /// The camera barcode scanner.
    /// </summary>
    ImagingCameraBarcodeScanner _cameraBarcodeScanner;

    /// <summary>
    /// Initializes a new instance of the <see cref="IsbnBarcodeScannerForm"/> class.
    /// </summary>
    public IsbnBarcodeScannerForm()
    {
        InitializeComponent();

        _cameraBarcodeScanner = new ImagingCameraBarcodeScanner();
        _cameraBarcodeScanner.BarcodeScanner.FrameScanFinished += BarcodeScanner_FrameScanFinished;
        _cameraBarcodeScanner.ScanningException += CameraBarcodeScanner_ScanningException;

        _cameraBarcodeScanner.BarcodeScanner.ScannerSettings.ScanBarcodeTypes = Vintasoft.Barcode.BarcodeType.QR;
    }

    /// <summary>
    /// Starts the capturing of images from seleced device and recognition of barcodes in captured images.
    /// </summary>
    private void startButton_Click(object sender, EventArgs e)
    {
        textBox1.Text = "Scan Barcodes Types: " + _cameraBarcodeScanner.BarcodeScanner.ScannerSettings.ScanBarcodeTypes.ToString();

        _cameraBarcodeScanner.CaptureDevice = _cameraBarcodeScanner.CaptureDevices[0];
        _cameraBarcodeScanner.StartScanning();
    }

    /// <summary>
    /// Stops the capturing of images from seleced device and recognition of barcodes in captured images.
    /// </summary>
    private void stopButton_Click(object sender, EventArgs e)
    {
        textBox1.Text = "";

        _cameraBarcodeScanner.StopScanning();
    }

    /// <summary>
    /// Shows an error.
    /// </summary>
    private void CameraBarcodeScanner_ScanningException(object sender, Vintasoft.Imaging.ExceptionEventArgs e)
    {
        MessageBox.Show(e.Exception.ToString());
    }

    /// <summary>
    /// Handles the FrameScanFinished event of the BarcodeScanner.
    /// </summary>
    private void BarcodeScanner_FrameScanFinished(object sender, Vintasoft.Barcode.FrameScanFinishedEventArgs e)
    {
        if (e.FoundBarcodes.Length > 0)
            Invoke(new ShowRecognitionResultsDelegate(ShowRecognitionResults), new object[] { e.FoundBarcodes });
    }

    /// <summary>
    /// Shows barcode recognition results.
    /// </summary>
    private void ShowRecognitionResults(Vintasoft.Barcode.IBarcodeInfo[] barcodes)
    {
        StringBuilder result = new StringBuilder();

        foreach (Vintasoft.Barcode.IBarcodeInfo barcode in barcodes)
            result.AppendLine(string.Format("{0}: {1}", barcode.BarcodeType, barcode.Value));

        // show barcode recognition in text box
        textBox1.Text = result.ToString();
    }

    delegate void ShowRecognitionResultsDelegate(Vintasoft.Barcode.IBarcodeInfo[] barcodeInfo);
}


/// <summary>
/// Allows to capture images from DirectShow camera (VintaSoft Imaging .NET SDK) and recognize barcodes in captured images (VintaSoft Barcode .NET SDK).
/// </summary>
public class ImagingCameraBarcodeScanner : IDisposable
{

    #region Fields

    /// <summary>
    /// Monitor for capture devices.
    /// </summary>
    Vintasoft.Imaging.Media.ImageCaptureDevicesMonitor _captureDevicesMonitor;

    /// <summary>
    /// Image capture source for barcode recognition.
    /// </summary>
    Vintasoft.Imaging.Media.ImageCaptureSource _imageCaptureSource;

    #endregion



    #region Constructors

    /// <summary>
    /// Initializes a new instance of the <see cref="ImagingCameraBarcodeScanner"/> class.
    /// </summary>
    public ImagingCameraBarcodeScanner()
    {
        _barcodeScanner = new Vintasoft.Barcode.CameraBarcodeScanner();
        _barcodeScanner.FrameScanException += BarcodeScanner_FrameScanException;
        _barcodeScanner.ScannerSettings.ScanBarcodeTypes = Vintasoft.Barcode.BarcodeType.ISBN;

        _captureDevicesMonitor = new Vintasoft.Imaging.Media.ImageCaptureDevicesMonitor();
        _captureDevicesMonitor.CaptureDevicesChanged += CaptureDevicesMonitor_CaptureDevicesChanged;

        if (!Vintasoft.Imaging.ImagingEnvironment.IsInDesignMode)
            _captureDevicesMonitor.Start();

        _imageCaptureSource = new Vintasoft.Imaging.Media.ImageCaptureSource();
        _imageCaptureSource.CaptureCompleted += ImageCaptureSource_CaptureCompleted;

    }

    #endregion



    #region Properties

    Vintasoft.Imaging.Media.ImageCaptureDevice _captureDevice;
    /// <summary>
    /// Gets or sets current capture device.
    /// </summary>
    public Vintasoft.Imaging.Media.ImageCaptureDevice CaptureDevice
    {
        get
        {
            return _captureDevice;
        }
        set
        {
            if (_captureDevice != value)
            {
                _captureDevice = value;

                UpdateCapureFormats();
            }
        }
    }

    ReadOnlyCollection<Vintasoft.Imaging.Media.ImageCaptureFormat> _captureFormats = null;
    /// <summary>
    /// Gets the available capture formats of current capture device.
    /// </summary>
    /// <seealso cref="CaptureDevice"/>
    public ReadOnlyCollection<Vintasoft.Imaging.Media.ImageCaptureFormat> CaptureFormats
    {
        get
        {
            return _captureFormats;
        }
    }

    /// <summary>
    /// Gets available capture devices.
    /// </summary>
    public ReadOnlyCollection<Vintasoft.Imaging.Media.ImageCaptureDevice> CaptureDevices
    {
        get
        {
            return Vintasoft.Imaging.Media.ImageCaptureDeviceConfiguration.GetCaptureDevices();
        }
    }

    Vintasoft.Barcode.CameraBarcodeScanner _barcodeScanner;
    /// <summary>
    /// Gets the barcode scanner.
    /// </summary>
    public Vintasoft.Barcode.CameraBarcodeScanner BarcodeScanner
    {
        get
        {
            return _barcodeScanner;
        }
    }

    /// <summary>
    /// Gets a value indicating whether barcode scanning is started.
    /// </summary>
    public bool IsStarted
    {
        get
        {
            return _imageCaptureSource.State == Vintasoft.Imaging.Media.ImageCaptureState.Started;
        }
    }

    #endregion



    #region Methods

    #region PUBLIC

    /// <summary>
    /// Starts the capturing of images from seleced device and recognition of barcodes in captured images.
    /// </summary>
    public void StartScanning()
    {
        try
        {
            if (CaptureDevice == null)
                throw new ArgumentNullException("CaptureDevice");

            if (CaptureFormats == null || CaptureFormats.Count == 0)
                throw new ArgumentNullException("CaptureFormats");

            if (_imageCaptureSource.State != Vintasoft.Imaging.Media.ImageCaptureState.Started)
            {
                if (CaptureDevice.DesiredFormat == null)
                    CaptureDevice.DesiredFormat = CaptureFormats[0];

                _barcodeScanner.StartScanning();

                _imageCaptureSource.CaptureDevice = _captureDevice;
                _imageCaptureSource.Start();
                _imageCaptureSource.CaptureAsync();

                OnScanningStart(EventArgs.Empty);
            }
        }
        catch (Exception ex)
        {
            OnScanningException(new Vintasoft.Imaging.ExceptionEventArgs(ex));
        }
    }

    /// <summary>
    /// Stops the capturing of images from seleced device and recognition of barcodes in captured images.
    /// </summary>
    public void StopScanning()
    {
        try
        {
            if (_imageCaptureSource.State != Vintasoft.Imaging.Media.ImageCaptureState.Stopped)
            {
                _barcodeScanner.StopScanning();
                _imageCaptureSource.Stop();

                OnScanningStop(EventArgs.Empty);
            }
        }
        catch (Exception ex)
        {
            OnScanningException(new Vintasoft.Imaging.ExceptionEventArgs(ex));
        }
    }

    /// <summary>
    /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
    /// </summary>
    public void Dispose()
    {
        _captureDevicesMonitor.CaptureDevicesChanged -= CaptureDevicesMonitor_CaptureDevicesChanged;
        _barcodeScanner.BarcodeReader.Dispose();
    }

    #endregion


    #region PROTECTED

    /// <summary>
    /// Raises the <see cref="CaptureDevicesChanged" /> event.
    /// </summary>
    /// <param name="args">The <see cref="ImageCaptureDevicesChangedEventArgs"/> instance containing the event data.</param>
    protected virtual void OnCaptureDevicesChanged(Vintasoft.Imaging.Media.ImageCaptureDevicesChangedEventArgs args)
    {
        if (CaptureDevicesChanged != null)
            CaptureDevicesChanged(this, args);
    }

    /// <summary>
    /// Raises the <see cref="ScanningException" /> event.
    /// </summary>
    /// <param name="args">The <see cref="ExceptionEventArgs"/> instance containing the event data.</param>
    protected virtual void OnScanningException(Vintasoft.Imaging.ExceptionEventArgs args)
    {
        if (ScanningException != null)
            ScanningException(this, args);
    }

    /// <summary>
    /// Raises the <see cref="ScanningStart" /> event.
    /// </summary>
    /// <param name="args">The <see cref="EventArgs"/> instance containing the event data.</param>
    protected virtual void OnScanningStart(EventArgs args)
    {
        if (ScanningStart != null)
            ScanningStart(this, args);
    }

    /// <summary>
    /// Raises the <see cref="ScanningStop" /> event.
    /// </summary>
    /// <param name="args">The <see cref="EventArgs"/> instance containing the event data.</param>
    protected virtual void OnScanningStop(EventArgs args)
    {
        if (ScanningStop != null)
            ScanningStop(this, args);
    }

    #endregion


    #region PRIVATE

    /// <summary>
    /// Handles the FrameScanException event of the BarcodeScanner control.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="Vintasoft.Barcode.FrameScanExceptionEventArgs"/> instance containing the event data.</param>
    private void BarcodeScanner_FrameScanException(object sender, Vintasoft.Barcode.FrameScanExceptionEventArgs e)
    {
        OnScanningException(new Vintasoft.Imaging.ExceptionEventArgs(e.Exception));
    }

    /// <summary>
    /// Handles the CaptureCompleted event of the ImageCaptureSource.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="ImageCaptureCompletedEventArgs"/> instance containing the event data.</param>
    private void ImageCaptureSource_CaptureCompleted(object sender, Vintasoft.Imaging.Media.ImageCaptureCompletedEventArgs e)
    {
        try
        {
            // get captured image
            Vintasoft.Imaging.VintasoftImage image = e.GetCapturedImage();

            // recognize barcodes from captured image
            using (Vintasoft.Imaging.VintasoftBitmap bitmap = image.GetAsVintasoftBitmap())
                _barcodeScanner.ScanFrame(bitmap);

            // if image capturing is started
            if (_imageCaptureSource.State == Vintasoft.Imaging.Media.ImageCaptureState.Started)
            {
                // capture next image
                _imageCaptureSource.CaptureAsync();
            }
        }
        catch (Exception ex)
        {
            OnScanningException(new Vintasoft.Imaging.ExceptionEventArgs(ex));
        }
    }

    /// <summary>
    /// Handles the CaptureDevicesChanged event of the CaptureDevicesMonitor.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="ImageCaptureDevicesChangedEventArgs"/> instance containing the event data.</param>
    private void CaptureDevicesMonitor_CaptureDevicesChanged(object sender, Vintasoft.Imaging.Media.ImageCaptureDevicesChangedEventArgs e)
    {
        if (Array.IndexOf(e.RemovedDevices, CaptureDevice) >= 0)
        {
            StopScanning();
        }

        OnCaptureDevicesChanged(e);
    }

    /// <summary>
    /// Updates the capture formats.
    /// </summary>
    private void UpdateCapureFormats()
    {
        Vintasoft.Imaging.Media.ImageCaptureDevice device = CaptureDevice;
        if (device == null || device.SupportedFormats == null)
        {
            _captureFormats = null;
        }
        else
        {
            List<Vintasoft.Imaging.Media.ImageCaptureFormat> captureFormats = new List<Vintasoft.Imaging.Media.ImageCaptureFormat>();

            List<uint> imageCaptureFormatSizes = new List<uint>();
            for (int i = 0; i < device.SupportedFormats.Count; i++)
            {
                // if format has bit depth less or equal than 12 bit
                if (device.SupportedFormats[i].BitsPerPixel <= 12)
                {
                    // ignore formats with bit depth less or equal than 12 bit because they may cause issues on Windows 8
                    continue;
                }

                uint imageCaptureFormatSize = (uint)(device.SupportedFormats[i].Width | (device.SupportedFormats[i].Height << 16));
                if (!imageCaptureFormatSizes.Contains(imageCaptureFormatSize))
                {
                    imageCaptureFormatSizes.Add(imageCaptureFormatSize);

                    captureFormats.Add(device.SupportedFormats[i]);
                }
            }
            _captureFormats = captureFormats.AsReadOnly();
        }
    }

    #endregion

    #endregion



    #region Events

    /// <summary>
    /// Occurs when barcode scanning is started.
    /// </summary>
    public event EventHandler ScanningStart;

    /// <summary>
    /// Occurs when barcode scanning is stopped.
    /// </summary>
    public event EventHandler ScanningStop;

    /// <summary>
    /// Occurs when barcode scanning error occurs.
    /// </summary>
    public event EventHandler<Vintasoft.Imaging.ExceptionEventArgs> ScanningException;

    /// <summary>
    /// Occurs when <see cref="CaptureDevices"/> property is changed.
    /// </summary>
    public event EventHandler<Vintasoft.Imaging.Media.ImageCaptureDevicesChangedEventArgs> CaptureDevicesChanged;

    #endregion

}