Python计算机视觉第七章-图像搜索

目录

7.1 基于内容的图像检索

从文本挖掘中获取灵感------矢量空间模型

7.2 视觉单词

7.3 图像索引

7.3.1 建立数据库

7.3.2 添加图像

7.4 在数据库中搜索图像

7.5 使用几何特性对结果排序


7.1 基于内容的图像检索

在大型图像数据库上,CBIR技术用于检索在视觉上具相似性的图像。在过去的几年里,研究者成功地引入文本挖掘技术到 CBIR 中处理问题,使在数百万图像中搜索具有相似内容的图像成为可能。

从文本挖掘中获取灵感------矢量空间模型

矢量空间模型是一个用于表示和搜索文本文档的模型。矢量包含了每个单词出现的次数,由于其忽略了单词出现的顺序及位置,该模型也被称为 BOW 表示模型。

最常用的权重是 tf-idf ( term frequency-inverse document frequency ,词频 - 逆向文
档频率 ) ,单词 w 在文档 d 中的 词频 是:

nw 是单词 w 在文档 d 中出现的次数。为了归一化,将 n w 除以整个文档中单词的总数。
逆向文档频率为:

|D| 是在语料库 D 中文档的数目,分母是语料库中包含单词 w 的文档数 d 。将两者
相乘可以得到矢量 v 中对应元素的 tf-idf 权重。

7.2 视觉单词

为了将文本挖掘技术应用到图像中,我们首先需要建立视觉等效单词;这通常可以 采用 2.2 节中介绍的 SIFT 局部描述子做到。它的思想是将描述子空间量化成一些典型实例,并将图像中的每个描述子指派到其中的某个实例中。这些典型实例可以通 过分析训练图像集确定,并被视为视觉单词。所有这些视觉单词构成的集合称为视觉词汇,有时也称为视觉码本。

利用一些聚类算法可以构建出视觉图像,搜索 聚类算法中最常用的是 K-means 1 ,这里也将采用 K-means 。
下面是关于聚类算法可以构建出视觉图像的实验:
实验代码:

python 复制代码
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.datasets import load_sample_image

# 加载样例图像
china = load_sample_image("china.jpg")
image = china / 255.0  # 归一化

# 将图像转换为二维数组
w, h, d = image.shape
image_array = image.reshape((w * h, d))

# 设置K-means参数
k = 16  # 选择16种颜色
kmeans = KMeans(n_clusters=k, random_state=0).fit(image_array)

# 将聚类结果应用于图像
segmented_img = kmeans.cluster_centers_[kmeans.labels_]
segmented_img = segmented_img.reshape((w, h, d))

# 绘制结果
plt.figure(figsize=(12, 6))

plt.subplot(1, 2, 1)
plt.title('Original Image')
plt.imshow(image)

plt.subplot(1, 2, 2)
plt.title('Segmented Image')
plt.imshow(segmented_img)

plt.show()

分析:

  • 使用sklearnKMeans来对图像进行聚类。
  • 图像被转换为二维数组,以便K-means算法处理。
  • 设定16种颜色(k=16)进行图像压缩。
  • 聚类结果应用回图像中,得到每个像素的颜色对应其簇的中心颜色。

结果:

7.3 图像索引

在开始搜索之前,我们需要建立图像数据库和图像的视觉单词表示。

7.3.1 建立数据库

在索引图像前,我们需要建立一个数据库。这里,我们使用 SQLite 作为数据库。

python 复制代码
import pickle
from pysqlite2 import dbapi2 as sqlite

class Indexer(object):
    def __init__(self, db, voc):
        """ 初始化数据库的名称及词汇对象 """
        self.con = sqlite.connect(db)
        self.voc = voc

    def __del__(self):
        """ 关闭数据库连接 """
        self.con.close()

    def db_commit(self):
        """ 提交数据库事务 """
        self.con.commit()

    def create_tables(self):
        """ 创建数据库表单及索引 """
        self.con.execute('CREATE TABLE IF NOT EXISTS imlist (filename TEXT)')
        self.con.execute('CREATE TABLE IF NOT EXISTS imwords (imid INTEGER, wordid INTEGER, vocname TEXT)')
        self.con.execute('CREATE TABLE IF NOT EXISTS imhistograms (imid INTEGER, histogram BLOB, vocname TEXT)')
        
        self.con.execute('CREATE INDEX IF NOT EXISTS im_idx ON imlist (filename)')
        self.con.execute('CREATE INDEX IF NOT EXISTS wordid_idx ON imwords (wordid)')
        self.con.execute('CREATE INDEX IF NOT EXISTS imid_idx ON imwords (imid)')
        self.con.execute('CREATE INDEX IF NOT EXISTS imidhist_idx ON imhistograms (imid)')
        
        self.db_commit()
python 复制代码
from indexer import Indexer

if __name__ == "__main__":
    # 创建词汇对象(在此示例中,我们将其设置为None,仅用于展示)
    voc = None

    # 指定数据库文件名称
    db_name = 'example.db'

    # 创建 Indexer 实例
    indexer = Indexer(db_name, voc)

    # 创建表单和索引
    indexer.create_tables()

    print(f"Database '{db_name}' and tables created successfully.")

创建完数据库后,查询表名以判断是否创建成功:

7.3.2 添加图像

有了数据库表单,我们便可以在索引中添加图像。为了实现该功能,我们需要在Indexer 类中添加 add_to_index() 方法。

下面是一个基本的实验代码示例,演示如何在数据库中添加图像,并进行分析和结果展示。

python 复制代码
import sqlite3
import os

# 连接到数据库(如果数据库不存在,会自动创建)
conn = sqlite3.connect('images.db')
cursor = conn.cursor()

# 创建一个表用于存储图像
cursor.execute('''
CREATE TABLE IF NOT EXISTS image_data (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT,
    data BLOB
)
''')


def insert_image(image_path):
    # 读取图像文件并转换为二进制数据
    with open(image_path, 'rb') as file:
        img_data = file.read()

    # 插入图像数据到数据库
    cursor.execute('INSERT INTO image_data (name, data) VALUES (?, ?)',
                   (os.path.basename(image_path), img_data))
    conn.commit()


def fetch_image(image_id, output_path):
    # 从数据库中获取图像数据
    cursor.execute('SELECT data FROM image_data WHERE id = ?', (image_id,))
    img_data = cursor.fetchone()[0]

    # 将图像数据写入文件
    with open(output_path, 'wb') as file:
        file.write(img_data)


# 实验操作
insert_image('1.jpg')
fetch_image(1, 'retrieved_image.jpg')

# 关闭数据库连接

分析:

  1. 创建表 :在数据库中创建一个 image_data 表用于存储图像数据。表中有两个字段:name(图像名称)和 data(图像二进制数据)。

  2. 插入图像insert_image 函数读取指定路径的图像文件,将其二进制数据插入到数据库中。

  3. 提取图像fetch_image 函数从数据库中获取指定 id 的图像数据,并将其保存为新文件。

结果:

7.4 在数据库中搜索图像

下面是在数据库中搜索图像的实验,image_data 表存储图像的元数据和图像文件本身(以 BLOB 格式存储)

实验代码:

python 复制代码
import sqlite3
import io
from PIL import Image

# 连接到 SQLite 数据库
conn = sqlite3.connect('images.db')
cursor = conn.cursor()

# 查询图像(假设按名称搜索)
def search_image_by_name(image_name):
    query = 'SELECT name, data FROM image_data WHERE name = ?'
    cursor.execute(query, (image_name,))
    result = cursor.fetchone()
    
    if result:
        img_name, img_data = result
        # 将二进制数据转为图像对象
        image = Image.open(io.BytesIO(img_data))
        image.show()  # 显示图像
        return img_name, image
    else:
        print("Image not found.")
        return None, None

# 示例搜索图像
image_name, image_obj = search_image_by_name('example_image.jpg')

# 关闭数据库连接
conn.close()

分析:

  1. 连接到数据库 :使用 sqlite3.connect 连接到 SQLite 数据库文件 images.db
  2. 执行查询search_image_by_name 函数接收一个图像名称作为参数,使用 SQL 查询从 image_data 表中检索图像数据。? 是参数化查询的占位符,防止 SQL 注入。
  3. 处理图像数据
    • fetchone() 获取查询结果(假设结果只有一行)。
    • io.BytesIO(img_data) 将图像的 BLOB 数据转换为字节流。
    • Image.open 用于将字节流转换为图像对象,并使用 show() 显示图像。
  4. 关闭连接:在操作完成后,关闭数据库连接。

结果:

表明从数据库中搜出次图像。

7.5 使用几何特性对结果排序

对图像进行几何特性排序通常涉及到提取图像的几何特征(如图像的面积、长宽比、边界框等),然后根据这些特征对图像进行排序。下面是一个示例,演示如何提取图像的几何特征并对图像进行排序。

实验代码:

python 复制代码
import sqlite3
import io
import cv2
import numpy as np
from PIL import Image

# 连接到 SQLite 数据库
conn = sqlite3.connect('images.db')
cursor = conn.cursor()


# 查询所有图像数据
def fetch_all_images():
    query = 'SELECT name, data FROM image_data'
    cursor.execute(query)
    return cursor.fetchall()


# 计算图像的几何特征(这里以面积为例)
def calculate_image_area(img_data):
    # 将二进制数据转为图像对象
    image = Image.open(io.BytesIO(img_data))
    # 转为 OpenCV 格式
    open_cv_image = np.array(image)
    if len(open_cv_image.shape) == 3:
        open_cv_image = cv2.cvtColor(open_cv_image, cv2.COLOR_RGB2GRAY)  # 转为灰度图
    # 计算图像的面积(即像素总数)
    area = np.sum(open_cv_image > 0)  # 计算非零像素的数量
    return area


# 获取图像并按面积排序
def get_sorted_images_by_area():
    images = fetch_all_images()
    image_areas = []

    for name, data in images:
        area = calculate_image_area(data)
        image_areas.append((name, area))

    # 按面积排序
    sorted_images = sorted(image_areas, key=lambda x: x[1], reverse=True)
    return sorted_images


# 输出排序结果
sorted_images = get_sorted_images_by_area()
for name, area in sorted_images:
    print(f"Image Name: {name}, Area: {area}")

# 关闭数据库连接
conn.close()

分析:

  1. 连接到数据库 :通过 sqlite3.connect 连接到 SQLite 数据库 images.db
  2. 提取图像数据fetch_all_images 函数从数据库中提取所有图像数据。
  3. 计算几何特征
    • calculate_image_area 函数将图像数据转换为 OpenCV 格式,然后计算图像的面积。我们将图像转换为灰度图,并计算非零像素的数量来估算面积。
  4. 排序图像get_sorted_images_by_area 函数获取所有图像及其面积,并根据面积进行排序。
  5. 输出结果:打印每个图像的名称和计算出的面积

结果:

因为此数据库中是三张一样的图,所以显示相同。

相关推荐
CV实验室1 天前
Meta引爆3D革命!SAM 3D 发布:单张图秒建3D模型,AR/VR、游戏圈炸锅!
计算机视觉·3d·meta·ar·vr
RFdragon1 天前
分享本周所学——三维重建算法3D Gaussian Splatting(3DGS)
人工智能·线性代数·算法·机器学习·计算机视觉·矩阵·paddlepaddle
星河耀银海1 天前
3D效果:HTML5 WebGL结合AI实现智能3D场景渲染
前端·人工智能·深度学习·3d·html5·webgl
balmtv1 天前
2026年多模态AI文件处理与联网搜索完全教程:国内镜像方案实测
人工智能
2501_926978331 天前
AI的三次起落发展分析,及未来预测----理论5.0的应用
人工智能·经验分享·笔记·ai写作·agi
前网易架构师-高司机1 天前
带标注的瓶盖识别数据集,识别率99.5%,可识别瓶盖,支持yolo,coco json,pascal voc xml格式
人工智能·yolo·数据集·瓶盖
软件供应链安全指南1 天前
以AI治理AI|问境AIST首家通过信通院大模型安全扫描产品能力评估!
人工智能·安全·ai安全·问境aist·aist·智能体安全
_爱明1 天前
CUDA索引越界问题(Compile with `TORCH_USE_CUDA_DSA` to enable device-side assertions)
人工智能·深度学习
这张生成的图像能检测吗1 天前
(论文速读)TCN:序列建模不一定需要 RNN
人工智能·深度学习·transformer·卷积·时序预测
大师影视解说1 天前
基于Web端的AI电影解说自动化生产工具实测:4步完成从文案到成片的全流程
运维·人工智能·自动化·影视解说·电影解说工具·网页版电影解说·ai电影解说