ich versuche mit Python eine Kamera zu steuern und die Kameradaten auszulesen. Vom Kamera Hersteller habe ich eine DLL (eigentlich 8 DDLs, die sich gegenseitig laden) und eine "lib" Datei mit zugehöriger Header Datei. Die Kamera hat eine Auflösung von 640x512 Pixel mit einer Frame Rate von 50 Bilder pro Sekunde (16 Bit Daten schwarz/weiß). Um die Daten aufzunehmen, wird von der Kamera Firmware beim initialisieren ein Ringbuffer aufgebaut, der kontinuierlich mit Daten gefüllt wird. Werden die Daten abgefragt (DLL Funktion GetImage()) erhält man einen C Zeiger, der wiederum einen Zeiger enthält, der auf den Speicheranfang des zuletzt vollständig aufgenommen Bildes zeigt. Bei jedem weiteren Aufruf wird immer nur der zweite Speicherbereichszeiger entsprechend auf einen neuen Bereich im Ringbuffer umgesetzt.
Als erstes habe ich versuch mit "ctypes" die DLL direkt anzusprechen:
Code: Alles auswählen
import numpy as np
import ctypes
import ctypes.wintypes
if __name__ == '__main__':
KameraDLL = ctypes.cdll.LoadLibrary("CAMERA_DeviceControl.dll")
ImageDaten_Flat = np.zeros(640 * 512, dtype=np.uint16)
ptr = ctypes.POINTER(ctypes.c_short)()
Result = KameraDLL.GetImage(ctypes.byref(ptr))
for i in range(640*512): # Daten in numpy array umkopieren
ImageDaten_Flat[i]=ptr[i]
ImageDaten_Flat.reshape(640, 512)
....
....
1. ich muß die Daten in ein "numy" Feld umkopieren, um sinnvoll damit arbeiten zu können (siehe die "for" Schleife im Code Beispiel). Jede andere Variante die Daten um zu kopieren (lambda Form, [:], ...) führt dazu, daß der Python Interpreter einfach stehen bleibt (Prozessorlast 0%, aber nichts passiert mehr)
2. die Konstruktion läuft nur unter "main". Aufruf in einer Unterroutine (Klassen Methode) führt direkt zum Stillstand des Python Interpreter
Da ich trotz verschiedener Hinweise im Netz keine zufriedenstellende Lösung hin bekommen habe, dachte ich das Problem mit einer C-Erweiterung zu umgehen( Compilieren erfolgt mit "distutils" und "Mingw" Compiler):
Code: Alles auswählen
#include <Python.h>
#define BOOL unsigned int
#define WORD unsigned short
#define DWORD unsigned int
#define BYTE unsigned char
#define CAMERA_API __declspec(dllexport)
#define CPUFIRMWAREDOWNLOADINITIATED -100
CAMERA_API int CAMERA_InitSystem(void);
CAMERA_API int CAMERA_GetImage(WORD** ppImage);
static PyObject* __init__(PyObject *self, PyObject *args)
{
printf("CAMERA Initialisierung laeuft"); /* wird spaeter benoetigt */
return Py_None;
}
static PyObject* InitSystem(PyObject *self, PyObject *args)
{
int Result;
char buf[5];
while(1) {
Result = CAMERA_InitSystem();
if(Result == CPUFIRMWAREDOWNLOADINITIATED) {
printf("Wait while Camera is initializing");
continue;
}
else if(Result) {
itoa(Result, buf, 10);
PyErr_SetString(PyExc_ValueError, strcat("CAMERA_InitSystem() returned error ", buf));
return(NULL);
}
else return Py_None;
}
}
static PyObject* SetIllumination(PyObject *self, PyObject *args)
{
int Illu;
if(!PyArg_ParseTuple(args, "i", &Illu)) {
PyErr_SetString(PyExc_ValueError, "hier wollte ich nicht hin");
return(NULL);
}
if( (Illu < 90) || (Illu > 180) ) {
PyErr_SetString(PyExc_ValueError, "ungueltiger Wert fuer Helligkeit [90, 180]");
return NULL;
}
return Py_None;
}
static PyObject* Exit(PyObject *self, PyObject *args)
{
OCT_Exit();
return Py_None;
}
static PyMethodDef CAMERA_DeviceControlMethods[] =
{
{"__init__", __init__, METH_VARARGS, "Kamera initialisieren"},
{"CAMERA_InitSystem", InitSystem, METH_VARARGS, "Kamera Geraet initialisieren"},
{"CAMERA_SetIllumination", SetIllumination, METH_VARARGS, "Kamera Helligkeit einstellen"},
{"CAMERA_Exit", Exit, METH_VARARGS, "Kamera System beenden"},
{NULL, NULL, 0, NULL},
};
static PyMethodDef ModuleMethods[] = { {NULL} };
#ifdef __cplusplus
extern "C"
#endif
void initCAMERA_DeviceControl()
{
PyMethodDef *def;
/* create a new module and class */
PyObject *module = Py_InitModule("CAMERA_DeviceControl", ModuleMethods);
PyObject *moduleDict = PyModule_GetDict(module);
PyObject *classDict = PyDict_New();
PyObject *className = PyString_FromString("CAMERA_DeviceControl");
PyObject *CAMERA_DeviceControlClass = PyClass_New(NULL, classDict, className);
PyDict_SetItemString(moduleDict, "CAMERA_DeviceControl", CAMERA_DeviceControlClass);
Py_DECREF(classDict);
Py_DECREF(className);
Py_DECREF(CAMERA_DeviceControlClass);
/* add methods to class */
for (def = CAMERA_DeviceControlMethods; def->ml_name != NULL; def++) {
PyObject *func = PyCFunction_New(def, NULL);
PyObject *method = PyMethod_New(func, NULL, CAMERA_DeviceControlClass);
PyDict_SetItemString(classDict, def->ml_name, method);
Py_DECREF(func);
Py_DECREF(method);
}
}
Code: Alles auswählen
# -*- coding: utf-8 -*-
"""
Created on Tue May 29 08:16:53 2012
@author: HS
@status: Nur Testdatei
@summary: Test Klassen erzeugen in C als Python Erweiterung
"""
import CAMERA_DeviceControl
if __name__ == '__main__':
Kamera = CAMERA_DeviceControl.CAMERA_DeviceControl()
Kamera.CAMERA_InitSystem()
print(" ------------ Helligkeit setzen", Kamera.CAMERA_SetIllumination(110))
Kamera.CAMERA_Exit()
print("----- Fertig ---")
Leider funktioniert diese Konstruktion völlig unberechenbar.
1.tes Problem: auch hier kommt es zu einem Speicher Problem. Wird die Initialisierung der Kamera aufgerufen, klappt dies, aber beim Aufruf der Funktion (CAMERA_SetIllumination()) steht der Python Interpreter wieder. Der C-Code Teil
Code: Alles auswählen
static PyObject* SetIllumination(PyObject *self, PyObject *args)
{
int Illu;
if(!PyArg_ParseTuple(args, "i", &Illu)) {
PyErr_SetString(PyExc_ValueError, "hier wollte ich nicht hin");
return(NULL);
}
...
...
2. kommentiere ich die Initialisierung aus erscheint, beim Aufruf der Funktion CAMERA_SetIllumination() die Fehlermeldung die im Code vorgesehen ist
Nach dieser länglichen Ausführung zu meinen beiden Fragen:
1. die Kamera DLL reserviert sehr viel Speicher (wahrscheinlich mit malloc() o.ä), der sich der Kontrolle von Python entzieht, aber anscheinend doch vom Python Heap Space abgezogen wird --> daher hängt sich der Python Interpreter in der reinen Python Lösung, aber auch in der C-Variante auf.
Gibt es also eine Möglichkeit die DLL außerhalb des Python Heap Space zu instanzieren (entweder in Python direkt oder als C-Code Lösung oder einer Compiler Einstellung)?
2. wieso erscheint beim Aufruf der Kamera Funktion CAMERA_SetIllumination() die Fehlermeldung, obwohl der Parameter Aufruf richtig zu sein scheint
Als System verwende ich Windows XP und Windows Vista (32 Bit Systeme, Verhalten ist auf beiden Systemen nahezu gleich) mit dem Paket "pythonxy" (Python 2.7.3 mit numpy 1.6.1)
Ich bin für jede Hilfe dankbar, da meine Alternative darin besteht alles, incl. Grafikausgabe in C umsetzen zu müssen.
Horst