将结构从 Python 传递给 C++ 或将 numpy 数组而不是文件地址传递给 Yolo
Passing a structre from Python to C++ OR passing a numpy array instead of file address to Yolo
我正在尝试将内存中的图像而不是文件地址传递给 Yolo。
在 source code 中,它使用 openCV 读取图像。由于 openCV return c++ 中的一种 mat 格式,因此它使用 mat_to_image(mat im)
函数将 mat 格式转换为图像格式。
但是 python 中的 opencv 使用 numpy.ndarray
所以我不能使用 mat_to_image()
.
所以我尝试按照作者的代码 here 自己将 numpy 数组放入图像格式 here 我们有:
class IMAGE(ctypes.Structure):
_fields_ = [("w", ctypes.c_int),
("h", ctypes.c_int),
("c", ctypes.c_int),
("data", ctypes.POINTER(ctypes.c_float))]
这是我的:
import darknet as dn
im = cv2.imdecode(in-memory_bytelike_object, cv2.IMREAD_COLOR)
h,w,c = im.shape
my_image = IMAGE()
my_image.w = ctypes.c_int(w)
my_image.h = ctypes.c_int(h)
my_image.c = ctypes.c_int(c)
my_image.data = im.ctypes.data_as(ctypes.POINTER(ctypes.c_float))
print(dn.detect(net, meta, my_image))
我也这样修改了detect
函数:
def detect(net, meta, image, thresh=.5, hier_thresh=.5, nms=.45):
# im = load_image(image, 0, 0) //image_address->mat (using cv2)-> image (using mat_to_image) and return image
im = image
...
但是当我 运行 它时,我得到这个错误:
ArgumentError: argument 2: <class 'TypeError'>: expected IMAGE instance instead of IMAGE
我想问题是我没有以正确的方式传递数据结构,但我不确定。
我阅读了一些关于在 Python 和 C++ 之间传递数据结构的其他答案,但我认为在我的情况下应该有一个更简单的解决方案。
好吧,我是这样做到的:
以下是将 numpy 数组转换为图像格式的方法:
import darknet as dn
def array_to_image(arr):
arr = arr.transpose(2,0,1)
c = arr.shape[0]
h = arr.shape[1]
w = arr.shape[2]
arr = (arr/255.0).flatten()
data = dn.c_array(dn.c_float, arr)
im = dn.IMAGE(w,h,c,data)
return im
使用问题中提到的 detect
函数的修改版本。
所以它是这样的:
im = cv2.imdecode(in-memory_bytelike_object, cv2.IMREAD_COLOR)
im = array_to_image(arr)
dn.rgbgr_image(im)
print(dn.detect(net, meta, im))
我正在尝试将内存中的图像而不是文件地址传递给 Yolo。
在 source code 中,它使用 openCV 读取图像。由于 openCV return c++ 中的一种 mat 格式,因此它使用 mat_to_image(mat im)
函数将 mat 格式转换为图像格式。
但是 python 中的 opencv 使用 numpy.ndarray
所以我不能使用 mat_to_image()
.
所以我尝试按照作者的代码 here 自己将 numpy 数组放入图像格式 here 我们有:
class IMAGE(ctypes.Structure):
_fields_ = [("w", ctypes.c_int),
("h", ctypes.c_int),
("c", ctypes.c_int),
("data", ctypes.POINTER(ctypes.c_float))]
这是我的:
import darknet as dn
im = cv2.imdecode(in-memory_bytelike_object, cv2.IMREAD_COLOR)
h,w,c = im.shape
my_image = IMAGE()
my_image.w = ctypes.c_int(w)
my_image.h = ctypes.c_int(h)
my_image.c = ctypes.c_int(c)
my_image.data = im.ctypes.data_as(ctypes.POINTER(ctypes.c_float))
print(dn.detect(net, meta, my_image))
我也这样修改了detect
函数:
def detect(net, meta, image, thresh=.5, hier_thresh=.5, nms=.45):
# im = load_image(image, 0, 0) //image_address->mat (using cv2)-> image (using mat_to_image) and return image
im = image
...
但是当我 运行 它时,我得到这个错误:
ArgumentError: argument 2: <class 'TypeError'>: expected IMAGE instance instead of IMAGE
我想问题是我没有以正确的方式传递数据结构,但我不确定。
我阅读了一些关于在 Python 和 C++ 之间传递数据结构的其他答案,但我认为在我的情况下应该有一个更简单的解决方案。
好吧,我是这样做到的:
以下是将 numpy 数组转换为图像格式的方法:
import darknet as dn
def array_to_image(arr):
arr = arr.transpose(2,0,1)
c = arr.shape[0]
h = arr.shape[1]
w = arr.shape[2]
arr = (arr/255.0).flatten()
data = dn.c_array(dn.c_float, arr)
im = dn.IMAGE(w,h,c,data)
return im
使用问题中提到的 detect
函数的修改版本。
所以它是这样的:
im = cv2.imdecode(in-memory_bytelike_object, cv2.IMREAD_COLOR)
im = array_to_image(arr)
dn.rgbgr_image(im)
print(dn.detect(net, meta, im))