在视频中找到特定的物体 + SIFT算法

一、工具准备

1.python3.6的安装

  下载的官网:https://www.python.org/getit/

  装好后,然后配置一下环境变量,就可以在cmd下使用python了


 2.在python下安装cv2

(1)cmd框中输入pip install cv2,若安装成功,则恭喜你一次性成功,如提示“无法找到与你当前版本的匹配”则尝试第2种方法。

(2)手动下载cv2包,解压后将cv2.pyd放到site_packages的目录下,下载地址:https://pypi.python.org/pypi/cv2-wrapper/0.1


 3.安装numpy

在cmd中输入如下:pip install numpy


二、思路分析

1.读取图像

# 读取一张图片
# 使用opencv读取图 ,直接返回numpy.ndarray对象,通道顺序为BGR,注意是BGR,通道值默认范围0-255
image = cv2.imread(imagepath)


2.读取视频,将视频一帧一帧读取

def readVideo(videopath, image):
    # 打开视频文件:在实例化的同时进行初始化
    cap = cv2.VideoCapture(videopath)
    # 检测是否正常打开:成功打开时,isOpened返回ture
    while(cap.isOpened()):
        # 获取每一帧的图像frame
        ret, frame = cap.read()
        # 这里必须加上判断视频是否读取结束的判断,否则播放到最后一帧的时候出现问题了
        if ret == True:
            start = time.time()
            # 将从视频中的获取的图像与要找的图像进行匹配
            found = matchSift(image, frame)
            end = time.time()
            print(end-start)
            # 获取原图像的大小
            width, height= found.shape[:2]
            # 将原图像缩小到原来的二分之一
            size = (int(height/2), int(width/2))
            found = cv2.resize(found, size, interpolation=cv2.INTER_AREA)
            # 显示图片
            cv2.imshow("found", found)
        else:
            break
        # 因为视频是7.54帧每秒,因此每一帧等待133ms - 62ms
        if cv2.waitKey(133-int((end-start)*1000)) & 0xFF == ord('q'):
            break
    # 停止在最后的一帧图像上
    cv2.waitKey()
    # 如果任务完成了,就释放一切
    cap.release()
    # 关掉所有已打开的GUI窗口
    cv2.destroyAllWindows()


3.图像识别处理

本文中采用的SIFT提取视频中的和待检测图像特征点,并利用特征点之间的映射关系找到视频中待检测物体的位置,绘制出绿色的边界并显示出来。
# 自己定义的函数 matchSift(image, frame)
found = matchSift(image, frame)

4、自己定义的函数 matchSift(image, frame)

def matchSift(findimg, img):
    """转换成灰度图片"""
    gray1 = cv2.cvtColor(findimg, cv2.COLOR_BGR2GRAY)
    gray2 = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    """创建SIFT对象"""
    sift = cv2.xfeatures2d.SIFT_create()
    """创建FLAN匹配器"""
    matcher = cv2.FlannBasedMatcher(dict(algorithm=1, trees=5), {})
    """检测关键点并计算键值描述符"""
    kpts1, descs1 = sift.detectAndCompute(gray1, None)
    kpts2, descs2 = sift.detectAndCompute(gray2, None)
    """KnnMatt获得Top2"""
    matches = matcher.knnMatch(descs1, descs2, 2)
    """根据他们的距离排序"""
    matches = sorted(matches, key=lambda x: x[0].distance)
    """比率测试,以获得良好的匹配"""
    good = [m1 for (m1, m2) in matches if m1.distance < 0.7 * m2.distance]
    canvas = img.copy()
    """发现单应矩阵"""
    """当有足够的健壮匹配点对(至少个MIN_MATCH_COUNT)时"""
    if len(good) >= MIN_MATCH_COUNT:
        """从匹配中提取出对应点对"""
        """小对象的查询索引,场景的训练索引"""
        src_pts = np.float32([kpts1[m.queryIdx].pt for m in good]).reshape(-1, 1, 2)
        dst_pts = np.float32([kpts2[m.trainIdx].pt for m in good]).reshape(-1, 1, 2)
        """利用匹配点找到CV2.RANSAC中的单应矩阵"""
        M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0)
        """计算图1的畸变,也就是在图2中的对应的位置"""
        h, w = findimg.shape[:2]
        pts = np.float32([[0, 0], [0, h-1], [w-1, h-1], [w-1, 0]]).reshape(-1, 1, 2)
        dst = cv2.perspectiveTransform(pts, M)
        """绘制边框"""
        cv2.polylines(canvas, [np.int32(dst)], True, (0, 255, 0), 3, cv2.LINE_AA)
    else:
        print("Not enough matches are found - {}/{}".format(len(good), MIN_MATCH_COUNT))
        return img
    return canvas


5.主函数

if __name__=="__main__":
    # 视频的路径
    videopath = r'D:\python_image\video.mp4'
    # 要匹配图片的路径
    imagepath = r'D:\python_image\image.jpg'
    # 读取一张图片
    image = cv2.imread(imagepath)
    # 读取视频,并识别
    readVideo(videopath, image)


三、结果

因为在这里发布不了视频,只能用一张图片来展示了

目标图片

在视频中找到特定的物体 + SIFT算法_第1张图片

要里面匹配目标图片的图片

在视频中找到特定的物体 + SIFT算法_第2张图片

结果

在视频中找到特定的物体 + SIFT算法_第3张图片


四、总结

SIFT算法特点: 

SIFT特征是图像的局部特征,其对旋转、尺度缩放、亮度变化保持不变性,对视角变化、仿射变换、噪声也保持一定程度的稳定性

独特性(Distinctiveness)好,信息量丰富,适用于在海量特征数据库中进行快速、准确的匹配

多量性,即使少数的几个物体也可以产生大量SIFT特征向量

经过优化的SIFT算法可满足一定的速度需求

可扩展性,可以很方便的与其他形式的特征向量进行



你可能感兴趣的:(在视频中找到特定的物体 + SIFT算法)