蠡測 2022-07-13 15:09 采纳率: 57.1%
浏览 17
已结题

opencv以图识图

问题遇到的现象和发生背景

想问一下如何建立book.csv 让封面和书名匹配

问题相关代码,请勿粘贴截图
import numpy as np
import glob
import csv
import cv2


class CoverDescriptor:
    def describe(self, image):
        descriptor = cv2.BRISK_create()
        (kps, descs) = descriptor.detectAndCompute(image, None)
        kps = np.float32([kp.pt for kp in kps])
        return (kps, descs)


class CoverMatcher:
    def __init__(self, descriptor, coverPaths, ratio=0.7, minMatches=40,
                 useHamming=True):
        self.descriptor = descriptor
        self.coverPaths = coverPaths
        self.ratio = ratio
        self.minMatches = minMatches
        self.distanceMethod = "BruteForce"
        if useHamming:
            self.distanceMethod += "-Hamming"

    def search(self, queryKps, queryDescs):
        # 创建results字典
        results = {}

        # 封面图片循环
        for coverPath in self.coverPaths:
            cover = cv2.imread(coverPath)
            gray = cv2.cvtColor(cover, cv2.COLOR_BGR2GRAY)
            (kps, descs) = self.descriptor.describe(gray)

            # query是待查图片的特征信息,后面的是当前数据库里每一张图片的信息
            score = self.match(queryKps, queryDescs, kps, descs)
            # 把score存入字典,字典的键固定为50个,值为对应的匹配分
            results[coverPath] = score


        # if matches were found, sort them
        if len(results) > 0:
            results = sorted([(v, k) for (k, v) in results.items() if v > 0],
                             reverse=True)
        return results

    def match(self, kpsA, featuresA, kpsB, featuresB):
        # 新建一个描述匹配的对象,方法是BruteForce-Hamming
        matcher = cv2.DescriptorMatcher_create(self.distanceMethod)
        # 对两幅图片的特征描述做knn近邻匹配
        rawMatches = matcher.knnMatch(featuresB, featuresA, 2)
        matches = []

        for m in rawMatches:
            if len(m) == 2 and m[0].distance < m[1].distance * self.ratio:
                matches.append((m[0].trainIdx, m[0].queryIdx))

        # check to see if there are enough matches to process
        if len(matches) > self.minMatches:
            # construct the two sets of points
            ptsA = np.float32([kpsA[i] for (i, _) in matches])
            ptsB = np.float32([kpsB[j] for (_, j) in matches])

            # compute the homography between the two sets of points
            # and compute the ratio of matched points
            (_, status) = cv2.findHomography(ptsA, ptsB, cv2.RANSAC, 4.0)

            # return the ratio of the number of matched keypoints
            # to the total number of keypoints
            return float(status.sum()) / status.size

        # no matches were found
        return -1.0



# 封面图片的路径
coverPath = r"C:\opencv\source"
# 待查询照片的路径
queryPath = r"C:\opencv\search\search1.jpg"


# 书本数据库,里面保存了照片-作者-书名
bookDatabasePath = "books.csv"
# 新建一个保存封面的字典
bookDatabase = {}
# 把csv里面的数据放入字典,字典的键就是照片名,值就是作者,书名信息
for book in csv.reader(open(bookDatabasePath)):
    # book 读出来是“书名,作者,其他等信息”
    bookDatabase[book[0]] = book[1:]

# 初始化封面描述和封面匹配对象
# 封面描述需要指定描述方法
cd = CoverDescriptor()
# 封面匹配需要指定距离度量方法,例如Hamming
cm = CoverMatcher(cd, glob.glob(coverPath + "*.jpg"), ratio=0.7, minMatches=40)

# 加载查询图像
queryImage = cv2.imread(queryPath)
# 降噪,转换成灰度图
gray = cv2.cvtColor(queryImage, cv2.COLOR_BGR2GRAY)
# 提取关键点和描述子
(queryKps, queryDescs) = cd.describe(gray)

# 注意这个cm是CoverMatcher,search是CoverMatcher里面的一个方法
# 在已有的数据库中进行匹配,返回匹配分数和匹配对象的路径,注意这里的路径表达里面有个转义字符
# 举例,某一个返回值是[(0.9871794871794872, 'covers\\cover016.png')]
results = cm.search(queryKps, queryDescs)
# print(cd.describe(gray))
print(bookDatabase)
# 显示出待查询的封面
cv2.imshow("query", queryImage)

# 如果在数据库里没有找到书的封面
if len(results) == 0:
    print("没有找到")
    cv2.waitKey(0)
else:
    # results的格式是[(0.9871794871794872, 'covers\\cover016.png')]
    for i, (score, coverPath) in enumerate(results):
        # rfind和find不同,rfind找出最右边的字符
        # 在字典中查询coverPath对应的值,首先需要提取'covers\\cover016.png'中的'cover016.png',注意这里需要使用转义反斜杠
        # 也可以这样使用coverPath.split('||')[-1]
        (author, title) = bookDatabase[coverPath[coverPath.rfind("\\") + 1:]]
        # (author,title) = bookDatabase[coverPath.split("\\")[-1]]

        # 打印输出结果,百分比保留2位小数点
        print("loop{} precision is {:.2f}%: author is {} - title is {}".format(i + 1, score * 100, author, title))
        # 这个coverPath是对应数据库文件里的图片
        result = cv2.imread(coverPath)
        cv2.imshow("results", result)
        cv2.waitKey(0)
cv2.destroyAllWindows()

运行结果及报错内容
我的解答思路和尝试过的方法
我想要达到的结果
  • 写回答

0条回答 默认 最新

    报告相同问题?

    问题事件

    • 系统已结题 7月21日
    • 创建了问题 7月13日

    悬赏问题

    • ¥100 求汇川机器人IRCB300控制器和示教器同版本升级固件文件升级包
    • ¥15 用visualstudio2022创建vue项目后无法启动
    • ¥15 x趋于0时tanx-sinx极限可以拆开算吗
    • ¥500 把面具戴到人脸上,请大家贡献智慧
    • ¥15 任意一个散点图自己下载其js脚本文件并做成独立的案例页面,不要作在线的,要离线状态。
    • ¥15 各位 帮我看看如何写代码,打出来的图形要和如下图呈现的一样,急
    • ¥30 c#打开word开启修订并实时显示批注
    • ¥15 如何解决ldsc的这条报错/index error
    • ¥15 VS2022+WDK驱动开发环境
    • ¥30 关于#java#的问题,请各位专家解答!