首页 > 解决方案 > OpenCV python不显示转换为OpenCV关键点格式的python包装的Cuda SIFT关键点

问题描述

我们使用 pybind11 围绕 ExtractSift 函数编写了一个小型 python 包装器,它似乎工作正常。

这是它的样子:

std::vector<SiftPoint> extractSIFT(char* filename)
{
    int devNum = 0, imgSet = 0;
    cv::Mat img;
    cv::imread(filename, 0).convertTo(img, CV_32FC1);
    unsigned int w = img.cols;
    unsigned int h = img.rows;

    InitCuda(devNum);
    CudaImage img1;
    img1.Allocate(w, h, iAlignUp(w, 128), false, NULL, (float*)img.data);
    img1.Download();
    
    SiftData siftData1;
    float initBlur = 1.0f;
    float thresh = (imgSet ? 4.5f : 3.0f);
    InitSiftData(siftData1, 32768, true, true); 
    float *memoryTmp = AllocSiftTempMemory(w, h, 5, false);
    ExtractSift(siftData1, img1, 5, initBlur, thresh, 0.0f, false, memoryTmp);
    FreeSiftTempMemory(memoryTmp);
    return std::vector<SiftPoint>(siftData1.h_data, siftData1.h_data + siftData1.numPts);
}

PYBIND11_MODULE(pycusift, m) {
    m.doc() = "SIFT feature extractor with CUDA"; // optional module docstring

    m.def("extractSIFT", &extractSIFT, "function to extract SIFT features from image");
    py::class_<SiftPoint>(m, "SiftPoint")
    .def(py::init<>())
    .def_readwrite("xpos", &SiftPoint::xpos)
    .def_readwrite("ypos", &SiftPoint::ypos)
    .def_readwrite("sharpness", &SiftPoint::sharpness)
    .def_readwrite("edgeness", &SiftPoint::edgeness)
    .def_readwrite("ambiguity", &SiftPoint::ambiguity)
    .def_readwrite("orientation", &SiftPoint::orientation)
    .def_readwrite("score", &SiftPoint::score)
    .def_readwrite("match", &SiftPoint::match)
    .def_readwrite("match_xpos", &SiftPoint::match_xpos)
    .def_readwrite("match_ypos", &SiftPoint::match_ypos)
    .def_readwrite("match_error", &SiftPoint::match_error)
    .def_readwrite("subsampling", &SiftPoint::ypos)
    .def_readwrite("scale", &SiftPoint::scale)
    .def("getempty", &SiftPoint::getempty)
    .def("getdata", &SiftPoint::getdata);
}

这种类型的用法正确地绘制了关键点


import pycusift

a = pycusift.extractSIFT("001.tiff")
x = [i.xpos for i in a]
y = [i.ypos for i in a]
import matplotlib.pyplot as plt
import cv2
plt.imshow(cv2.imread("001.tiff"))
plt.scatter(x,y)
plt.show() 

以下代码尝试使用 opencv 显示关键点,但没有显示关键点,我认为这可能是浮点类型转换问题


def extract_sift_keypoints(impath, kpts):
    im = cv.imread(impath, cv.IMREAD_COLOR)
    kp = cv.KeyPoint()
    kp1 = []
    desc1 = (np.array([k.getdata() for k in kpts], dtype=np.float32))
    

    for k in kpts :
        kp.pt = (k.xpos, k.ypos)
        kp.angle = k.orientation
        kp.size = k.scale
        kp1.append(kp)

    pts = np.array([k.pt for k in kp1], dtype=np.float32)
    ors = np.array([k.angle for k in kp1], dtype=np.float32)
    scs = np.array([k.size for k in kp1], dtype=np.float32) 

    return pts, ors, scs, desc1, im, kp1

if __name__ == '__main__':
    p = argparse.ArgumentParser()

    opt = p.parse_args()
    kpts1 = pycusift.extractSIFT(opt.im1)
    k1, o1, s1, d1, im1, kps1 = extract_sift_keypoints(opt.im1,kpts1)
   
    outimg = np.empty((im1.shape[0], im1.shape[1], 3), dtype=np.uint8)
    cv.drawKeypoints(im1, kps1, outimg)
    cv.imshow("kp", outimg)
    cv.waitKey(0)    

    print(type(kps1[0].pt))
    print(kps1[0].pt)
    print(type(kps1[0].angle))
    print(kps1[0].angle)
    bf = cv.BFMatcher()
    matches = bf.knnMatch(d1,d2, k=2)

我必须指出,我认为的 knn 描述符匹配正在生成匹配项

这是打印语句的输出:

<类'元组'>

(431.0779724121094, 982.3478393554688)

<类'浮动'>

224.15390014648438

标签: pythonc++opencvsiftpybind11

解决方案


我找到了解决方案,必须将 kp = cv.keypoint() 放入 for 循环中:

def extract_sift_keypoints(impath, kpts):
    im = cv.imread(impath, cv.IMREAD_COLOR)
    kp1 = []
    desc1 = (np.array([k.getdata() for k in kpts], dtype=np.float32))
    

    for k in kpts :
        kp = cv.KeyPoint()
        kp.pt = (k.xpos, k.ypos)
        kp.angle = k.orientation
        kp.size = k.scale
        kp1.append(kp)

    pts = np.array([k.pt for k in kp1], dtype=np.float32)
    ors = np.array([k.angle for k in kp1], dtype=np.float32)
    scs = np.array([k.size for k in kp1], dtype=np.float32) 

    return pts, ors, scs, desc1, im, kp1

推荐阅读