使用级联Softmax和广义大幅度损失训练的改进DCNN进行细粒度图像分类

摘要:

利用一般的深卷积神经网络(DCNN)设计了一种细粒度的图像分类器。我们从以下两个方面提高了DCNN模型的细粒度图像分类精度。首先,为了更好地建模包含在给定训练数据集中的细粒度图像类的h级分层标签结构,我们引入h完全连接(Fc)层来代替给定DCNN模型的顶层fc层,并用级联Softmax损失对其进行训练。
其次,我们提出了一种新的损失函数,即广义大边界损失(GLM)损失,使给定的DCNN模型能够显式地探索细粒度图像类的层次标签结构和相似规律。GLM损失不仅减少了DCNN模型学习特征的类间相似度和类内方差,而且使属于同一粗类的子类在特征空间中比属于不同粗类的子类更加相似。此外,所提出的细粒度图像分类框架是独立的,适用于任何DCNN结构。利用三个基准数据集(StanfordCar、细粒度视觉分类飞机和CUB-200-2011)对几种常用的DCNN模型(AlexNet、Google LeNet和VGG)进行了综合实验评估,验证了该方法的有效性。

关键词:级联Softmax损失,深卷积神经网络(DCNN),细粒度图像分类,广义大边界(GLM)损失,分层标签结构。

1.引言:

细粒度图像分类的目的是识别某些基类的子类,如不同模型的CARS[1]-[5]、鸟类的种类[5]-[9]、飞机的变体[10]、[11]等。它具有广泛的应用,如视频监控车辆模型识别、细粒度图像内容标注、垂直搜索等。细粒度图像分类面临的挑战主要来自两个方面:类间相似性和类内方差[12]-[16]。
一方面,不同细粒度类之间的视觉差异可能非常小且微妙。另一方面,由于位置、视点、姿势、照明条件等的不同,属于同一细粒度类的实例可能具有明显的不同外观。例如,图中所示的“加利福尼亚海鸥”。1(A)在视觉上与图中的“环嘴鸥”非常相似。1(B),它们之间唯一显著的区别在于它们喙上的图案。同时,由于姿态、视点和光照条件的不同,不同图像中的“加利福尼亚海鸥”(如“环嘴鸥”)呈现出明显的不同外观。

在这里插入图片描述
对于细粒度的图像分类任务,文献[17]-[20]中提出了许多基于部分的分类方法。
这些方法首先检测目标对象的不同部分,然后对局部部分的外观进行建模,以增加类间的识别率,同时减小类内的差异。例如,对于细粒度的鸟类分类,张等。[18]建议学习头部、喙和身体等零件的外观模型,并强制执行它们之间的几何约束。然而,基于零件的方法依赖于精确的零件检测,这是另一个具有挑战性的问题,在存在遮挡和较大视点/姿态变化的情况下可能会失败。此外,部件的检测器通常以有监督的方式进行训练,这需要足够多的训练样本。显然,与指定细粒度的图像标签相比,标注对象部分更具挑战性,也更昂贵。

最近的许多研究工作[4],[21]-[25]利用新的损失函数训练的深度卷积神经网络(DCNN),如对比损失[26],[27],三重损失[23]等,来学习能够最小化类内方差,同时最大化类间距离的特征。然而,当构成给定训练集的样本对或样本三胞胎时,对比和三胞胎损失都会受到数据扩展的影响。此外,据报告,构成训练样本对或三对样本的方式会对DCNN模型的性能精度产生几个百分点的重大影响[23]、[28]。因此,使用这种损失可能会导致模型收敛较慢、计算成本较高、训练复杂性增加和不确定性。

有研究工作提出了新的损失函数或专门的CNN结构,以利用不同细粒度类别之间的标签关系[4]、[5]、[28]、[29]或探讨输入图像不同部分之间的相关性[11]。这些方法在细粒度图像分类的各种基准数据集上都达到了最新的分类精度。
在本文中,我们开发了一个细粒度的图像分类器使用一个通用的DCNN。我们试图从以下两个方面提高DCNN模型的细粒度图像分类精度。首先,为了更好地对细粒度图像类的h级层次标签结构进行建模,我们将给定的DCNN模型的顶完全连接(FC)层替换为h FC层,每个层对应于分层标签结构的相应层次。h fc层中的每一层都是到其下层和功能输出层的fc,并使用来自相应标签层次结构的标签的Softmax丢失进行训练。本文将用于训练h FC层的h Softmax损耗称为级联Softmax损耗。
其次,我们提出了一种新的损失函数,即广义大边界损失(GLM),它明确地研究了细粒度图像类的层次标签结构和相似规律。更具体地说,对于每个给定的细粒度类c,我们将剩余的细粒度类分为两个组SP©和nSP©

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要测量图像中螺栓的尺寸,可以使用以下步骤: 1. 读取图像并转换为灰度图像 ```c++ Mat image = imread("bolts.jpg", IMREAD_COLOR); Mat gray_image; cvtColor(image, gray_image, COLOR_BGR2GRAY); ``` 2. 对灰度图像进行二值化处理 ```c++ Mat binary_image; threshold(gray_image, binary_image, 0, 255, THRESH_BINARY | THRESH_OTSU); ``` 3. 对二值化图像进行形态学操作,去除噪声并连接目标 ```c++ Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3)); morphologyEx(binary_image, binary_image, MORPH_OPEN, kernel); morphologyEx(binary_image, binary_image, MORPH_CLOSE, kernel); ``` 4. 对处理后的图像进行轮廓检测,并筛选出符合条件的轮廓 ```c++ vector<vector<Point>> contours; vector<Vec4i> hierarchy; findContours(binary_image, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE); vector<RotatedRect> rects; for (size_t i = 0; i < contours.size(); i++) { RotatedRect rect = minAreaRect(contours[i]); if (rect.size.width > 50 && rect.size.height > 50 && rect.size.width < 200 && rect.size.height < 200) { rects.push_back(rect); } } ``` 5. 在原图像中画出符合条件的轮廓,并输出目标的尺寸 ```c++ for (size_t i = 0; i < rects.size(); i++) { Rect rect = rects[i].boundingRect(); rectangle(image, rect, Scalar(0, 255, 0), 2); cout << "Bolt " << i << " size: " << rect.width << " x " << rect.height << endl; } ``` 完整代码如下: ```c++ #include <opencv2/opencv.hpp> #include <iostream> using namespace cv; using namespace std; int main() { // 读取图像并转化为灰度图像 Mat image = imread("bolts.jpg", IMREAD_COLOR); Mat gray_image; cvtColor(image, gray_image, COLOR_BGR2GRAY); // 对灰度图像进行二值化 Mat binary_image; threshold(gray_image, binary_image, 0, 255, THRESH_BINARY | THRESH_OTSU); // 对二值化图像进行形态学操作 Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3)); morphologyEx(binary_image, binary_image, MORPH_OPEN, kernel); morphologyEx(binary_image, binary_image, MORPH_CLOSE, kernel); // 对处理后的图像进行轮廓检测,并筛选出符合条件的轮廓 vector<vector<Point>> contours; vector<Vec4i> hierarchy; findContours(binary_image, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE); vector<RotatedRect> rects; for (size_t i = 0; i < contours.size(); i++) { RotatedRect rect = minAreaRect(contours[i]); if (rect.size.width > 50 && rect.size.height > 50 && rect.size.width < 200 && rect.size.height < 200) { rects.push_back(rect); } } // 在原图像中画出符合条件的轮廓,并输出目标的尺寸 for (size_t i = 0; i < rects.size(); i++) { Rect rect = rects[i].boundingRect(); rectangle(image, rect, Scalar(0, 255, 0), 2); cout << "Bolt " << i << " size: " << rect.width << " x " << rect.height << endl; } // 显示结果图像 namedWindow("Detected Bolts", WINDOW_NORMAL); imshow("Detected Bolts", image); waitKey(0); return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值