現在輕量C 相機SDK 已經完成,適用於Windows、Linux 和macOS,我們可以將其整合到其他高階程式語言中。在本文中,我們將探討如何基於 C 相機庫建立 Python 相機 SDK,並使用它與 Dynamsoft Barcode Reader SDK 進行多條碼掃描。
CPython 擴充功能是一個共享函式庫(例如,Windows 上的DLL、Linux 上的.so 或macOS 上的.dylib)可以在執行時載入到Python解釋器中並用於擴展其功能。 lite相機CPython擴充專案的結構如下:
python-lite-camera │ │── include │ ├── Camera.h │ ├── CameraPreview.h │ ├── stb_image_write.h │── lib │ ├── linux │ │ ├── liblitecam.so │ ├── macos │ │ ├── liblitecam.dylib │ ├── windows │ │ ├── litecam.dll │ │ ├── litecam.lib ├── src │ ├── litecam.cpp │ ├── pycamera.h │ ├── pywindow.h │── litecam │ ├── __init__.py │── setup.py │── MANIFEST.in │── README.md
說明:
在setup.py中加入以下內容:
from setuptools.command import build_ext from setuptools import setup, Extension import sys import os import io from setuptools.command.install import install import shutil from pathlib import Path lib_dir = '' sources = [ "src/litecam.cpp", ] include_dirs = [os.path.join(os.path.dirname(__file__), "include")] libraries = ['litecam'] extra_compile_args = [] if sys.platform == "linux" or sys.platform == "linux2": lib_dir = 'lib/linux' extra_compile_args = ['-std=c++11'] extra_link_args = ["-Wl,-rpath=$ORIGIN"] elif sys.platform == "darwin": lib_dir = 'lib/macos' extra_compile_args = ['-std=c++11'] extra_link_args = ["-Wl,-rpath,@loader_path"] elif sys.platform == "win32": lib_dir = 'lib/windows' extra_link_args = [] else: raise RuntimeError("Unsupported platform") long_description = io.open("README.md", encoding="utf-8").read() module_litecam = Extension( "litecam", sources=sources, include_dirs=include_dirs, library_dirs=[lib_dir], libraries=libraries, extra_compile_args=extra_compile_args, extra_link_args=extra_link_args, ) def copyfiles(src, dst): if os.path.isdir(src): filelist = os.listdir(src) for file in filelist: libpath = os.path.join(src, file) shutil.copy2(libpath, dst) else: shutil.copy2(src, dst) class CustomBuildExt(build_ext.build_ext): def run(self): build_ext.build_ext.run(self) dst = os.path.join(self.build_lib, "litecam") copyfiles(lib_dir, dst) filelist = os.listdir(self.build_lib) for file in filelist: filePath = os.path.join(self.build_lib, file) if not os.path.isdir(file): copyfiles(filePath, dst) os.remove(filePath) class CustomBuildExtDev(build_ext.build_ext): def run(self): build_ext.build_ext.run(self) dev_folder = os.path.join(Path(__file__).parent, 'litecam') copyfiles(lib_dir, dev_folder) filelist = os.listdir(self.build_lib) for file in filelist: filePath = os.path.join(self.build_lib, file) if not os.path.isdir(file): copyfiles(filePath, dev_folder) class CustomInstall(install): def run(self): install.run(self) setup(name='lite-camera', version='2.0.1', description='LiteCam is a lightweight, cross-platform library for capturing RGB frames from cameras and displaying them. Designed with simplicity and ease of integration in mind, LiteCam supports Windows, Linux and macOS platforms.', long_description=long_description, long_description_content_type="text/markdown", author='yushulx', url='https://github.com/yushulx/python-lite-camera', license='MIT', packages=['litecam'], ext_modules=[module_litecam], classifiers=[ "Development Status :: 5 - Production/Stable", "Environment :: Console", "Intended Audience :: Developers", "Intended Audience :: Education", "Intended Audience :: Information Technology", "Intended Audience :: Science/Research", "License :: OSI Approved :: MIT License", "Operating System :: Microsoft :: Windows", "Operating System :: MacOS", "Operating System :: POSIX :: Linux", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: C++", "Programming Language :: Python :: Implementation :: CPython", "Topic :: Scientific/Engineering", "Topic :: Software Development", ], cmdclass={ 'install': CustomInstall, 'build_ext': CustomBuildExt, 'develop': CustomBuildExtDev}, )
說明:
pycamera.h 檔案定義了用於從相機捕獲幀的 PyCamera Python 類,而 pywindow.h 檔案定義了用於在視窗中顯示幀的 PyWindow Python 類。 litecam.cpp 檔案作為 Python 擴充功能的入口點,其中定義了一些全域方法,並註冊了 PyCamera 和 PyWindow 類別。
python-lite-camera │ │── include │ ├── Camera.h │ ├── CameraPreview.h │ ├── stb_image_write.h │── lib │ ├── linux │ │ ├── liblitecam.so │ ├── macos │ │ ├── liblitecam.dylib │ ├── windows │ │ ├── litecam.dll │ │ ├── litecam.lib ├── src │ ├── litecam.cpp │ ├── pycamera.h │ ├── pywindow.h │── litecam │ ├── __init__.py │── setup.py │── MANIFEST.in │── README.md
from setuptools.command import build_ext from setuptools import setup, Extension import sys import os import io from setuptools.command.install import install import shutil from pathlib import Path lib_dir = '' sources = [ "src/litecam.cpp", ] include_dirs = [os.path.join(os.path.dirname(__file__), "include")] libraries = ['litecam'] extra_compile_args = [] if sys.platform == "linux" or sys.platform == "linux2": lib_dir = 'lib/linux' extra_compile_args = ['-std=c++11'] extra_link_args = ["-Wl,-rpath=$ORIGIN"] elif sys.platform == "darwin": lib_dir = 'lib/macos' extra_compile_args = ['-std=c++11'] extra_link_args = ["-Wl,-rpath,@loader_path"] elif sys.platform == "win32": lib_dir = 'lib/windows' extra_link_args = [] else: raise RuntimeError("Unsupported platform") long_description = io.open("README.md", encoding="utf-8").read() module_litecam = Extension( "litecam", sources=sources, include_dirs=include_dirs, library_dirs=[lib_dir], libraries=libraries, extra_compile_args=extra_compile_args, extra_link_args=extra_link_args, ) def copyfiles(src, dst): if os.path.isdir(src): filelist = os.listdir(src) for file in filelist: libpath = os.path.join(src, file) shutil.copy2(libpath, dst) else: shutil.copy2(src, dst) class CustomBuildExt(build_ext.build_ext): def run(self): build_ext.build_ext.run(self) dst = os.path.join(self.build_lib, "litecam") copyfiles(lib_dir, dst) filelist = os.listdir(self.build_lib) for file in filelist: filePath = os.path.join(self.build_lib, file) if not os.path.isdir(file): copyfiles(filePath, dst) os.remove(filePath) class CustomBuildExtDev(build_ext.build_ext): def run(self): build_ext.build_ext.run(self) dev_folder = os.path.join(Path(__file__).parent, 'litecam') copyfiles(lib_dir, dev_folder) filelist = os.listdir(self.build_lib) for file in filelist: filePath = os.path.join(self.build_lib, file) if not os.path.isdir(file): copyfiles(filePath, dev_folder) class CustomInstall(install): def run(self): install.run(self) setup(name='lite-camera', version='2.0.1', description='LiteCam is a lightweight, cross-platform library for capturing RGB frames from cameras and displaying them. Designed with simplicity and ease of integration in mind, LiteCam supports Windows, Linux and macOS platforms.', long_description=long_description, long_description_content_type="text/markdown", author='yushulx', url='https://github.com/yushulx/python-lite-camera', license='MIT', packages=['litecam'], ext_modules=[module_litecam], classifiers=[ "Development Status :: 5 - Production/Stable", "Environment :: Console", "Intended Audience :: Developers", "Intended Audience :: Education", "Intended Audience :: Information Technology", "Intended Audience :: Science/Research", "License :: OSI Approved :: MIT License", "Operating System :: Microsoft :: Windows", "Operating System :: MacOS", "Operating System :: POSIX :: Linux", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: C++", "Programming Language :: Python :: Implementation :: CPython", "Topic :: Scientific/Engineering", "Topic :: Software Development", ], cmdclass={ 'install': CustomInstall, 'build_ext': CustomBuildExt, 'develop': CustomBuildExtDev}, )
PyCamera 結構體表示包裹 C Camera 物件的 Python 物件。此處理程序是一個指向 Camera 類別實例的指標。
PyCamera_dealloc
#include <Python.h> #include <structmember.h> #include "Camera.h"
解除分配 Camera 物件並釋放關聯的記憶體。
PyCamera_new
typedef struct { PyObject_HEAD Camera *handler; } PyCamera;
建立 PyCamera 的新實例。它為Python對象分配內存,創建一個新的Camera對象,並將其分配給self->handler。
開放
static int PyCamera_clear(PyCamera *self) { if (self->handler) { delete self->handler; } return 0; } static void PyCamera_dealloc(PyCamera *self) { PyCamera_clear(self); Py_TYPE(self)->tp_free((PyObject *)self); }
開啟指定索引的相機。
列表媒體類型
static PyObject *PyCamera_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyCamera *self; self = (PyCamera *)type->tp_alloc(type, 0); if (self != NULL) { self->handler = new Camera(); } return (PyObject *)self; }
傳回支援的媒體類型清單。對於 Windows,它將寬字串轉換為 Python Unicode 物件。
發布
static PyObject *open(PyObject *obj, PyObject *args) { PyCamera *self = (PyCamera *)obj; int index = 0; if (!PyArg_ParseTuple(args, "i", &index)) { return NULL; } bool ret = self->handler->Open(index); return Py_BuildValue("i", ret); }
釋放相機。
設定解析度
static PyObject *listMediaTypes(PyObject *obj, PyObject *args) { PyCamera *self = (PyCamera *)obj; std::vector<MediaTypeInfo> mediaTypes = self->handler->ListSupportedMediaTypes(); PyObject *pyList = PyList_New(0); for (size_t i = 0; i < mediaTypes.size(); i++) { MediaTypeInfo &mediaType = mediaTypes[i]; #ifdef _WIN32 PyObject *subtypeName = PyUnicode_FromWideChar(mediaType.subtypeName, wcslen(mediaType.subtypeName)); PyObject *pyMediaType = Py_BuildValue("{s:i,s:i,s:O}", "width", mediaType.width, "height", mediaType.height, "subtypeName", subtypeName); if (subtypeName != NULL) { Py_DECREF(subtypeName); } #else PyObject *pyMediaType = Py_BuildValue("{s:i,s:i,s:s}", "width", mediaType.width, "height", mediaType.height, "subtypeName", mediaType.subtypeName); #endif PyList_Append(pyList, pyMediaType); } return pyList; }
設定相機的解析度。
捕獲幀
static PyObject *release(PyObject *obj, PyObject *args) { PyCamera *self = (PyCamera *)obj; self->handler->Release(); Py_RETURN_NONE; }
從相機捕獲幀並將 RGB 資料作為 Python 位元組數組傳回。
getWidth 和 getHeight
static PyObject *setResolution(PyObject *obj, PyObject *args) { PyCamera *self = (PyCamera *)obj; int width = 0, height = 0; if (!PyArg_ParseTuple(args, "ii", &width, &height)) { return NULL; } int ret = self->handler->SetResolution(width, height); return Py_BuildValue("i", ret); }
傳回捕獲幀的寬度和高度。
static PyObject *captureFrame(PyObject *obj, PyObject *args) { PyCamera *self = (PyCamera *)obj; FrameData frame = self->handler->CaptureFrame(); if (frame.rgbData) { PyObject *rgbData = PyByteArray_FromStringAndSize((const char *)frame.rgbData, frame.size); PyObject *pyFrame = Py_BuildValue("iiiO", frame.width, frame.height, frame.size, rgbData); ReleaseFrame(frame); return pyFrame; } else { Py_RETURN_NONE; } }
定義 PyCamera Python 物件上可用的方法。這些方法與上面定義的對應 C 函數相關聯。
static PyObject *getWidth(PyObject *obj, PyObject *args) { PyCamera *self = (PyCamera *)obj; int width = self->handler->frameWidth; return Py_BuildValue("i", width); } static PyObject *getHeight(PyObject *obj, PyObject *args) { PyCamera *self = (PyCamera *)obj; int height = self->handler->frameHeight; return Py_BuildValue("i", height); }
定義 PyCamera 類型,包括其方法、記憶體分配、釋放和其他行為。
static PyMethodDef instance_methods[] = { {"open", open, METH_VARARGS, NULL}, {"listMediaTypes", listMediaTypes, METH_VARARGS, NULL}, {"release", release, METH_VARARGS, NULL}, {"setResolution", setResolution, METH_VARARGS, NULL}, {"captureFrame", captureFrame, METH_VARARGS, NULL}, {"getWidth", getWidth, METH_VARARGS, NULL}, {"getHeight", getHeight, METH_VARARGS, NULL}, {NULL, NULL, 0, NULL}};
static PyTypeObject PyCameraType = { PyVarObject_HEAD_INIT(NULL, 0) "litecam.PyCamera", /* tp_name */ sizeof(PyCamera), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)PyCamera_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_reserved */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ PyObject_GenericSetAttr, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ "PyCamera", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ instance_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ PyCamera_new, /* tp_new */ };
定義一個包裝 C CameraWindow 物件的 PyWindow 結構。 handler 成員指向 CameraWindow 的一個實例。
PyWindow_dealloc
#include <Python.h> #include <structmember.h> #include "CameraPreview.h"
取消分配CameraWindow物件並釋放記憶體。
PyWindow_new
typedef struct { PyObject_HEAD CameraWindow *handler; } PyWindow;
建立 PyWindow 的新實例。它為Python物件分配內存,建立一個新的CameraWindow對象,並將其分配給self->handler。
等待鍵
python-lite-camera │ │── include │ ├── Camera.h │ ├── CameraPreview.h │ ├── stb_image_write.h │── lib │ ├── linux │ │ ├── liblitecam.so │ ├── macos │ │ ├── liblitecam.dylib │ ├── windows │ │ ├── litecam.dll │ │ ├── litecam.lib ├── src │ ├── litecam.cpp │ ├── pycamera.h │ ├── pywindow.h │── litecam │ ├── __init__.py │── setup.py │── MANIFEST.in │── README.md
等待按鍵事件,如果按鍵與指定字元匹配則傳回 False。 False 意味著應用程式應該退出。
showFrame
from setuptools.command import build_ext from setuptools import setup, Extension import sys import os import io from setuptools.command.install import install import shutil from pathlib import Path lib_dir = '' sources = [ "src/litecam.cpp", ] include_dirs = [os.path.join(os.path.dirname(__file__), "include")] libraries = ['litecam'] extra_compile_args = [] if sys.platform == "linux" or sys.platform == "linux2": lib_dir = 'lib/linux' extra_compile_args = ['-std=c++11'] extra_link_args = ["-Wl,-rpath=$ORIGIN"] elif sys.platform == "darwin": lib_dir = 'lib/macos' extra_compile_args = ['-std=c++11'] extra_link_args = ["-Wl,-rpath,@loader_path"] elif sys.platform == "win32": lib_dir = 'lib/windows' extra_link_args = [] else: raise RuntimeError("Unsupported platform") long_description = io.open("README.md", encoding="utf-8").read() module_litecam = Extension( "litecam", sources=sources, include_dirs=include_dirs, library_dirs=[lib_dir], libraries=libraries, extra_compile_args=extra_compile_args, extra_link_args=extra_link_args, ) def copyfiles(src, dst): if os.path.isdir(src): filelist = os.listdir(src) for file in filelist: libpath = os.path.join(src, file) shutil.copy2(libpath, dst) else: shutil.copy2(src, dst) class CustomBuildExt(build_ext.build_ext): def run(self): build_ext.build_ext.run(self) dst = os.path.join(self.build_lib, "litecam") copyfiles(lib_dir, dst) filelist = os.listdir(self.build_lib) for file in filelist: filePath = os.path.join(self.build_lib, file) if not os.path.isdir(file): copyfiles(filePath, dst) os.remove(filePath) class CustomBuildExtDev(build_ext.build_ext): def run(self): build_ext.build_ext.run(self) dev_folder = os.path.join(Path(__file__).parent, 'litecam') copyfiles(lib_dir, dev_folder) filelist = os.listdir(self.build_lib) for file in filelist: filePath = os.path.join(self.build_lib, file) if not os.path.isdir(file): copyfiles(filePath, dev_folder) class CustomInstall(install): def run(self): install.run(self) setup(name='lite-camera', version='2.0.1', description='LiteCam is a lightweight, cross-platform library for capturing RGB frames from cameras and displaying them. Designed with simplicity and ease of integration in mind, LiteCam supports Windows, Linux and macOS platforms.', long_description=long_description, long_description_content_type="text/markdown", author='yushulx', url='https://github.com/yushulx/python-lite-camera', license='MIT', packages=['litecam'], ext_modules=[module_litecam], classifiers=[ "Development Status :: 5 - Production/Stable", "Environment :: Console", "Intended Audience :: Developers", "Intended Audience :: Education", "Intended Audience :: Information Technology", "Intended Audience :: Science/Research", "License :: OSI Approved :: MIT License", "Operating System :: Microsoft :: Windows", "Operating System :: MacOS", "Operating System :: POSIX :: Linux", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: C++", "Programming Language :: Python :: Implementation :: CPython", "Topic :: Scientific/Engineering", "Topic :: Software Development", ], cmdclass={ 'install': CustomInstall, 'build_ext': CustomBuildExt, 'develop': CustomBuildExtDev}, )
在視窗中顯示一個框架。
繪製輪廓
#include <Python.h> #include <structmember.h> #include "Camera.h"
在框架上繪製輪廓(一系列點)。
繪製文字
typedef struct { PyObject_HEAD Camera *handler; } PyCamera;
在框架上繪製文字。
static int PyCamera_clear(PyCamera *self) { if (self->handler) { delete self->handler; } return 0; } static void PyCamera_dealloc(PyCamera *self) { PyCamera_clear(self); Py_TYPE(self)->tp_free((PyObject *)self); }
定義 PyWindow Python 物件上可用的方法。
static PyObject *PyCamera_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyCamera *self; self = (PyCamera *)type->tp_alloc(type, 0); if (self != NULL) { self->handler = new Camera(); } return (PyObject *)self; }
定義 PyWindow 類型,包括其方法、記憶體分配、釋放和其他行為。
static PyObject *open(PyObject *obj, PyObject *args) { PyCamera *self = (PyCamera *)obj; int index = 0; if (!PyArg_ParseTuple(args, "i", &index)) { return NULL; } bool ret = self->handler->Open(index); return Py_BuildValue("i", ret); }
說明:
開發模式
static PyObject *listMediaTypes(PyObject *obj, PyObject *args) { PyCamera *self = (PyCamera *)obj; std::vector<MediaTypeInfo> mediaTypes = self->handler->ListSupportedMediaTypes(); PyObject *pyList = PyList_New(0); for (size_t i = 0; i < mediaTypes.size(); i++) { MediaTypeInfo &mediaType = mediaTypes[i]; #ifdef _WIN32 PyObject *subtypeName = PyUnicode_FromWideChar(mediaType.subtypeName, wcslen(mediaType.subtypeName)); PyObject *pyMediaType = Py_BuildValue("{s:i,s:i,s:O}", "width", mediaType.width, "height", mediaType.height, "subtypeName", subtypeName); if (subtypeName != NULL) { Py_DECREF(subtypeName); } #else PyObject *pyMediaType = Py_BuildValue("{s:i,s:i,s:s}", "width", mediaType.width, "height", mediaType.height, "subtypeName", mediaType.subtypeName); #endif PyList_Append(pyList, pyMediaType); } return pyList; }
輪組
static PyObject *release(PyObject *obj, PyObject *args) { PyCamera *self = (PyCamera *)obj; self->handler->Release(); Py_RETURN_NONE; }
來源分佈
static PyObject *setResolution(PyObject *obj, PyObject *args) { PyCamera *self = (PyCamera *)obj; int width = 0, height = 0; if (!PyArg_ParseTuple(args, "ii", &width, &height)) { return NULL; } int ret = self->handler->SetResolution(width, height); return Py_BuildValue("i", ret); }
安裝Python相機SDK和Dynamsoft Barcode Reader SDK:
static PyObject *captureFrame(PyObject *obj, PyObject *args) { PyCamera *self = (PyCamera *)obj; FrameData frame = self->handler->CaptureFrame(); if (frame.rgbData) { PyObject *rgbData = PyByteArray_FromStringAndSize((const char *)frame.rgbData, frame.size); PyObject *pyFrame = Py_BuildValue("iiiO", frame.width, frame.height, frame.size, rgbData); ReleaseFrame(frame); return pyFrame; } else { Py_RETURN_NONE; } }
取得 Dynamsoft Barcode Reader 30 天免費試用許可證。
建立用於多條碼掃描的 Python 腳本:
static PyObject *getWidth(PyObject *obj, PyObject *args) { PyCamera *self = (PyCamera *)obj; int width = self->handler->frameWidth; return Py_BuildValue("i", width); } static PyObject *getHeight(PyObject *obj, PyObject *args) { PyCamera *self = (PyCamera *)obj; int height = self->handler->frameHeight; return Py_BuildValue("i", height); }
將 LICENSE-KEY 替換為您的 Dynamsoft Barcode Reader 許可證金鑰。
運行腳本:
static PyMethodDef instance_methods[] = { {"open", open, METH_VARARGS, NULL}, {"listMediaTypes", listMediaTypes, METH_VARARGS, NULL}, {"release", release, METH_VARARGS, NULL}, {"setResolution", setResolution, METH_VARARGS, NULL}, {"captureFrame", captureFrame, METH_VARARGS, NULL}, {"getWidth", getWidth, METH_VARARGS, NULL}, {"getHeight", getHeight, METH_VARARGS, NULL}, {NULL, NULL, 0, NULL}};
https://github.com/yushulx/python-lite-camera
以上是建立 Python 相機 SDK 並使用它進行多條碼掃描的詳細內容。更多資訊請關注PHP中文網其他相關文章!