在OpenCV 3.4.8中如何从Python向C++传递cv::KeyPoint数组?
问题:Python向OpenCV C++传递cv::KeyPoint列表失败
背景信息
- cv::KeyPoint从Python视角的字段及类型:
x:np.float32y:np.float32size:np.float32angle:np.float32response:np.float32octave:np.int32class_id:np.int32
- 单组关键点数量通常为200-500+
Python端代码
# Detect keypoints and compute descriptors orb = cv2.ORB_create() keypoints1 = orb.detect(img1, None) keypoints2 = orb.detect(img2, None) keypoints1, descriptors1 = orb.compute(img1, keypoints1) keypoints2, descriptors2 = orb.compute(img2, keypoints2) # Convert keypoints to Python lists of cv::KeyPoint objects keypoints1_list = [cv2.KeyPoint(kp.pt[0], kp.pt[1], kp.size, kp.angle, kp.response, kp.octave, kp.class_id) for kp in keypoints1] keypoints2_list = [cv2.KeyPoint(kp.pt[0], kp.pt[1], kp.size, kp.angle, kp.response, kp.octave, kp.class_id) for kp in keypoints2] arr_kp1= np.ascontiguousarray(keypoints1_list) arr_kp2= np.ascontiguousarray(keypoints2_list) opencvwrapper.evaluateFeatureDetector(arr_img1, arr_img2, arr_kp1, arr_kp2)
C++端绑定代码(基于OpenCV 3.4.8 + pybind11)
float evaluateFeatureDetector(py::array_t<uint8_t>& arr1, py::array_t<uint8_t>& arr2, py::array_t<cv::KeyPoint>& keypoints1, py::array_t<cv::KeyPoint>& keypoints2){ ... cv::Mat H1to2= cv::findHomography(keypoints1, keypoints2, cv::RANSAC); // Do some more computations here }
错误信息
TypeError: evaluateFeatureDetector(): incompatible function arguments. The following argument types are supported: 1. (arg0: cv::Mat, arg1: cv::Mat, arg2: List[cv::KeyPoint], arg3: List[cv::KeyPoint]) -> float Invoked with: array([[[ 2, 4, 4], [ 1, 3, 3], [ 0, 2, 2], ..., [ 1, 4, 2], [ 0, 3, 1]]], dtype=uint8), array([[[12, 12, 12], [11, 11, 11], [11, 11, 11], ..., [44, 44, 44], [47, 47, 47], [47, 47, 47]]], dtype=uint8), [<KeyPoint 0x7f96a7239060>, <KeyPoint 0x7f96a7239090>, <KeyPoint 0x7f96a72390c0>, ...
已尝试的无效方法
- 使用
std::vector<cv::KeyPoint>&作为参数,报错;改用py::array_t<cv::KeyPoint>&后错误依旧 - 用
np.ascontiguousarray()转换关键点列表,但cv::KeyPoint不是numpy支持的数值类型 - 将C++参数改为float类型,导致
cv::findHomography()因输入类型不匹配报错
解决建议
1. 修正C++函数参数类型
错误提示已明确支持的参数类型,直接调整函数定义,同时确保包含STL转换的头文件:
#include <pybind11/stl.h> // 必须包含以支持std::vector与Python列表的自动转换 float evaluateFeatureDetector(cv::Mat& img1, cv::Mat& img2, std::vector<cv::KeyPoint>& keypoints1, std::vector<cv::KeyPoint>& keypoints2) { cv::Mat H1to2 = cv::findHomography(keypoints1, keypoints2, cv::RANSAC); // 后续计算逻辑 return 0.0f; // 根据实际需求返回结果 }
2. 简化Python端代码
不需要将关键点转为numpy数组,直接传递原始关键点列表即可:
# Detect keypoints and compute descriptors orb = cv2.ORB_create() keypoints1 = orb.detect(img1, None) keypoints2 = orb.detect(img2, None) keypoints1, descriptors1 = orb.compute(img1, keypoints1) keypoints2, descriptors2 = orb.compute(img2, keypoints2) # 直接传递原始关键点列表,无需额外转换 opencvwrapper.evaluateFeatureDetector(img1, img2, keypoints1, keypoints2)
3. 确认pybind11绑定配置
- 确保绑定代码中包含
pybind11/stl.h,pybind11会自动处理std::vector<cv::KeyPoint>与Python列表的转换 - OpenCV 3.4.8的
cv::Mat和cv::KeyPoint可被pybind11自动识别,无需额外配置
关键说明
- Python中的
cv::KeyPoint对象列表可直接被pybind11转换为C++的std::vector<cv::KeyPoint>,无需手动转numpy数组 - Python的numpy图像数组会自动转为C++的
cv::Mat,无需额外处理
内容的提问来源于stack exchange,提问作者dev_4a_living
相关产品推荐
相关产品推荐

