在计算机视觉领域,物种识别和图像相似度比较是两个重要的研究方向。本文通过结合深度学习和图像处理技术,基于opencv和tensorflow的mobilenetv2的预训练模型模,实现物种识别和个体相似度分析。本文详细介绍该实验过程并提供相关代码。
一、名词介绍
1. opencv
opencv(open source computer vision library)是一个开源的计算机视觉和机器学习软件库。opencv由英特尔公司在1999年发起,并在2000年以开源的方式发布。该库被设计为高效的计算机视觉应用程序开发工具,支持多种编程语言(如c++、python、java)和平台(如windows、linux、mac os、android、ios)。
使用opencv具有以下优势:
- 开源和免费:opencv是完全开源和免费的,这使得开发者可以自由地使用、修改和分发。
- 跨平台:opencv支持多个操作系统和平台,包括windows、linux、mac os、android和ios,使其在多种设备上具有广泛的适用性。
- 丰富的功能:opencv提供了广泛的功能,包括图像处理、视频分析、物体检测、机器学习、计算机视觉算法等,满足了大多数计算机视觉应用的需求。
- 大规模社区支持:opencv拥有一个活跃的社区,提供丰富的文档、教程和示例代码,开发者可以方便地获取支持和资源。
- 性能优化:opencv对性能进行了高度优化,支持硬件加速(如gpu),能够在实时应用中高效运行。
2. tensorflow
tensorflow是一个由google brain团队开发的开源深度学习框架。它提供了全面、灵活的工具,支持构建和训练各种深度学习模型。tensorflow支持多种平台,包括windows、linux、mac os和移动设备,并且可以利用cpu和gpu进行高效计算。
使用tensorflow具有以下优势:
- 灵活性和可扩展性:tensorflow支持构建和训练各种类型的深度学习模型,从简单的线性模型到复杂的神经网络。
- 跨平台支持:tensorflow支持在多个平台上运行,包括桌面系统、服务器和移动设备,并且可以利用gpu和tpu进行加速。
- 广泛的社区和生态系统:tensorflow拥有一个庞大的社区,提供丰富的资源和支持。其生态系统包括tensorboard(用于可视化)、tensorflow lite(用于移动设备)和tensorflow serving(用于部署)。
- 预训练模型和模型库:tensorflow提供了大量的预训练模型和模型库,可以方便地进行迁移学习和模型优化。
3. opencv与同类视库对比
下表对比了opencv与其他几种常见的计算机视觉库(如dlib、simplecv和scikit-image)的特点:
特性 | opencv | dlib | simplecv | scikit-image |
---|---|---|---|---|
开源和免费 | 是 | 是 | 是 | 是 |
跨平台支持 | windows, linux, mac os, android, ios | windows, linux, mac os | windows, linux, mac os | windows, linux, mac os |
编程语言支持 | c++, python, java, matlab | c++, python | python | python |
图像处理 | 广泛支持 | 支持 | 基础支持 | 广泛支持 |
视频处理 | 广泛支持 | 不支持 | 基础支持 | 不支持 |
机器学习算法 | 支持(集成了opencv ml模块) | 支持(内置多种机器学习算法) | 基础支持 | 支持(依赖scikit-learn) |
面部检测 | 支持(haar级联分类器、dnn) | 支持(hog+svm、cnn) | 支持 | 基础支持(依赖外部库) |
性能优化 | 高度优化,支持硬件加速 | 一定程度优化,部分支持硬件加速 | 未优化 | 一定程度优化 |
社区支持 | 活跃社区,大量资源 | 中等规模社区 | 小规模社区 | 中等规模社区 |
二、环境准备
1. 搭建python环境
为了避免和历史包版本的冲突,这里我先新建了一个新的conda环境,起名opencv。
python环境为3.8.19。
升级pip
和setuptools
,规避后面可能发生的包版本冲突等安装问题。
2. 安装必要的库
下面,我安装了程序依赖的必要库。因为我是边摸索边安装,所以没有一次性全部安装这些库,你可以全部浏览完本节内容后一口气安装。
用到的库及介绍:
库名称 | 介绍 |
---|---|
flask | 一个轻量级的web框架,用于构建web应用程序和api。 |
flask-cors | 一个flask扩展,用于处理跨域资源共享(cors)问题,使得前端可以访问后端api。 |
numpy | 一个用于科学计算的库,提供支持大型多维数组和矩阵的操作,以及大量的数学函数库。 |
opencv | 一个开源计算机视觉库,提供丰富的图像和视频处理功能。 |
tensorflow | 一个开源的机器学习框架,用于构建和训练各种机器学习模型。 |
keras | 高级神经网络api,运行在tensorflow之上,用于快速构建和训练深度学习模型。 |
scikit-learn | 一个用于机器学习的python库,提供简单高效的数据挖掘和数据分析工具,包括各种分类、回归和聚类算法。 |
下面是逐步安装的步骤:
① 安装flask、numpy、opencv-python库
pip install flask numpy opencv-python
② 安装flask-cors库
安装这个库主要原因是解决请求flask时的跨域问题。
pip install flask-cors
③ 安装tensorflow、keras库
tensorflow 是常用的深度学习框架。keras 是一个高级神经网络 api,它能够以 tensorflow, cntk 或者 theano 作为后端运行。
pip install tensorflow keras
④ 安装scikit-learn库
scikit-learn是一个用于机器学习的python库,提供简单高效的数据挖掘和数据分析工具,包括各种分类、回归和聚类算法。
pip install scikit-learn
⑤ 安装cosine_similarity库
该库用于个体相似度比较。
pip install cosine_similarity
三、搭建flask服务器
1. 编写图像识别python代码
创建一个名为app.py的文件,编写如下代码:
from flask import flask, request, jsonify
from flask_cors import cors
import numpy as np
import cv2
from tensorflow.keras.applications.mobilenet_v2 import mobilenetv2, preprocess_input, decode_predictions
from tensorflow.keras.preprocessing import image
from sklearn.metrics.pairwise import cosine_similarity
app = flask(__name__)
cors(app)
# 加载预训练的mobilenetv2模型
model = mobilenetv2(weights='imagenet', include_top=true)
def classify_image(img):
img = cv2.resize(img, (224, 224)) # mobilenetv2的输入尺寸为224x224
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
x = preprocess_input(x)
preds = model.predict(x)
return decode_predictions(preds, top=1)[0][0][1], model.predict(x) # 返回类别名称和特征向量
def calculate_similarity(feature1, feature2):
return cosine_similarity(feature1, feature2)[0][0]
@app.route('/compare', methods=['post'])
def compare_images():
file1 = request.files['image1']
file2 = request.files['image2']
npimg1 = np.frombuffer(file1.read(), np.uint8)
npimg2 = np.frombuffer(file2.read(), np.uint8)
img1 = cv2.imdecode(npimg1, cv2.imread_color)
img2 = cv2.imdecode(npimg2, cv2.imread_color)
# 分类和特征提取
class1, feature1 = classify_image(img1)
class2, feature2 = classify_image(img2)
if class1 != class2:
similarity = 0.0
risk_level = "低"
intervention = "否"
else:
similarity = calculate_similarity(feature1, feature2)
risk_level = "高" if similarity > 0.8 else "中" if similarity > 0.5 else "低"
intervention = "是" if similarity > 0.8 else "否"
return jsonify({
'similarity': f'{similarity * 100:.2f}%',
'risk_level': risk_level,
'intervention': intervention,
'class1': class1,
'class2': class2
})
if __name__ == '__main__':
app.run(debug=true)
2. 运行flask服务器
再anaconda中启动opencv环境的终端,运行以下命令启动flask服务器:
python app.py
服务器启动后,将会监听在本地的5000端口。
四、浏览器客户端调用
1. 页面前端代码实现
创建一个html文件(test.html),实现图片上传和结果展示功能,全部代码如下:
<!doctype html>
<html lang="zh-cn">
<head>
<meta charset="utf-8">
<title>图片对比</title>
<style>
body {
font-family: arial, sans-serif;
display: flex;
flex-direction: column;
align-items: center;
margin: 0;
padding: 20px;
}
.container {
display: flex;
justify-content: space-between;
width: 80%;
margin-bottom: 20px;
}
.image-box {
width: 45%;
border: 2px dashed #ccc;
padding: 10px;
text-align: center;
position: relative;
}
.image-box img {
max-width: 100%;
max-height: 200px;
display: none;
}
.image-box input {
display: none;
}
.upload-btn {
cursor: pointer;
color: #007bff;
text-decoration: underline;
}
.loading-bar {
width: 80%;
height: 20px;
background-color: #f3f3f3;
border: 1px solid #ccc;
margin-top: 10px;
display: none;
position: relative;
}
.loading-bar div {
width: 0;
height: 100%;
background-color: #4caf50;
position: absolute;
animation: loading 5s linear forwards;
}
@keyframes loading {
to {
width: 100%;
}
}
.result {
display: none;
margin-top: 20px;
}
</style>
</head>
<body>
<h1>图片对比</h1>
<div class="container">
<div class="image-box" id="box1">
<label for="upload1" class="upload-btn">上传图片</label>
<input type="file" id="upload1" accept="image/*">
<img id="image1" alt="左边文本抓取图片">
</div>
<div class="image-box" id="box2">
<label for="upload2" class="upload-btn">上传图片</label>
<input type="file" id="upload2" accept="image/*">
<img id="image2" alt="右边文本数据库图片">
</div>
</div>
<button id="compare-btn">人工智能对比</button>
<div class="loading-bar" id="loading-bar">
<div></div>
</div>
<div class="result" id="result">
<p>相似百分比: <span id="similarity">0%</span></p>
<p>相似度: <span id="risk-level">低</span></p>
<p>相同个体推测: <span id="intervention">否</span></p>
<p>图1种类: <span id="class1">-</span></p>
<p>图2种类: <span id="class2">-</span></p>
</div>
<script>
document.getelementbyid('upload1').addeventlistener('change', function(event) {
loadimage(event.target.files[0], 'image1', 'box1');
});
document.getelementbyid('upload2').addeventlistener('change', function(event) {
loadimage(event.target.files[0], 'image2', 'box2');
});
function loadimage(file, imgid, boxid) {
const reader = new filereader();
reader.onload = function(e) {
const img = document.getelementbyid(imgid);
img.src = e.target.result;
img.style.display = 'block';
document.queryselector(`#${boxid} .upload-btn`).style.display = 'none';
}
reader.readasdataurl(file);
}
document.getelementbyid('compare-btn').addeventlistener('click', function() {
const loadingbar = document.getelementbyid('loading-bar');
const result = document.getelementbyid('result');
const image1 = document.getelementbyid('upload1').files[0];
const image2 = document.getelementbyid('upload2').files[0];
if (!image1 || !image2) {
alert('请上传两张图片进行对比');
return;
}
const formdata = new formdata();
formdata.append('image1', image1);
formdata.append('image2', image2);
loadingbar.style.display = 'block';
result.style.display = 'none';
fetch('http://localhost:5000/compare', {
method: 'post',
body: formdata
})
.then(response => response.json())
.then(data => {
loadingbar.style.display = 'none';
result.style.display = 'block';
document.getelementbyid('similarity').innertext = data.similarity;
document.getelementbyid('risk-level').innertext = data.risk_level;
document.getelementbyid('intervention').innertext = data.intervention;
document.getelementbyid('class1').innertext = data.class1;
document.getelementbyid('class2').innertext = data.class2;
})
.catch(error => {
loadingbar.style.display = 'none';
alert('对比过程中发生错误,请重试');
console.error('error:', error);
});
});
</script>
</body>
</html>
2. 运行网页
双击运行,刚刚创建的test.html文件,效果如图:
上传左右图片,点击对比:
可以看到两只品种明显不同的狗相似度为0。
再比较两只相同品种的狗的相似度:
可以看到系统识别出了两只狗的种类相同,相似比也高达75.2%,但因为没有达到我们设置的80%的阈值,所以判断非同一个体。当然,这里的80%非常牵强,实际操作中难免误差较大。由于本文算法使用的是mobilenetv2预训练模型,并没有根据实际应用场景大量训练和调参,所以如果投入应用,仍需重新训练并根据实际效果定义阈值。
同一物种的识别结果:
五、实验总结
本文介绍了基于opencv和深度学习的物种识别和个体相似度比较方法。通过使用预训练的mobilenetv2模型进行特征提取和分类,并结合余弦相似度计算,实现了物种识别和相似度比较。此方法在计算机视觉领域具有广泛的应用前景,可以用于各种图像识别和比较任务。
通过本文的示例代码,你可以快速搭建一个图像识别和比较系统,并根据需要进行进一步的优化和扩展。如果在实现过程中遇到问题,请随时联系我获取更多帮助。
发表评论