GALLERY SET、PROBE SET

本文深入探讨了人脸识别系统中关键集合的概念:训练集、参考图像集(gallery set)与测试图像集(probeset)。通过引用相关论文,解释了这些集合在评估协议中的角色与作用,强调了训练过程与测试阶段的分离,以及系统参数的不可调整性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Deng Cai的Learning a Spatially Smooth Subspace for Face Recognition 4.1节也有,和朱师弟讨论此处 gallery set等同于训练集,Probe set等同于测试集; Graph Embedding and Extensions A General Framework for Dimensionality Reduction的4.1.1节的前一段最后意义与前相同
该论文的19页有如下描述:在FERET 评估协议中,算法设计者 需要区分三个不同的集合:训练集,参考图像集(或者
原型图像集,gallery set)、测试图像集合(Probe set),其中gallery  集和probe 集供测试时使用。“
练必须在测试开始之前完成”暗示训练是离线完成的,算法不能根据Gallery 集来调整系统参数。 

具体见 http://parnec.nuaa.edu.cn/xtan/paper/TanXY-thesis-final.pdf
该论文的19页有如下描述:在FERET 评估协议中,算法设计者需要区分三个不同的集合:训练集 参考图像集(或者
原型图像集,gallery set)、测试图像集合(Probe set=test set),其中gallery 集和probe 集供测试时使用。“训
练必须在测试开始之前完成”暗示训练是离线完成的,算法不能根据Gallery 集来调整系统参数。

通过和Ran He老师讨论已经彻底搞清楚了:

比如他的CVPR 2012论文,用PCA+NN。人脸识别是一个开集问题,人脸验证verification是一个闭集问题。训练样本可能是甲乙,测试样本可能是丙丁。通过训练样本来学习PCA的投影向量。gallery相当于新的训练集,在Probe上测试。在The CAS-PEAL large-scale Chinese face database and baseline evaluations (TSMCA 2008)P155也有Training set、 gallery set、Probe set定义

摘自:http://www.cppblog.com/guijie/archive/2008/09/16/61952.html

Surveillance Face Recognition Challenge # ======================== Dataset Structure ========================== # "Training_Set": Ordered by face identities, i.e. each directory contains face images from a specific training identity. There are a total of 5,319 directories each is named by the corresponding identity. The image file name is in format of [PersonID]_[CameraID]_[ImageName].jpg. "Face_Identification_Test_Set" -"gallery": containing 60,294 gallery images from 5,319 test identities (IDs). -"mated_probe": containing 60,423 probe images from 5,319 test IDs, with mated gallery true match images in the "gallery" folder. -"unmated_probe": containing 12,1736 distractor probe face images without mated gallery true match images in the "gallery" folder, i.e. the open-set face identification scenario. -"gallery_img_ID_pairs.mat": the gallery image names and the corresponding face IDs -"mated_probe_img_ID_pairs.mat": the mated probe image names and the corresponding face IDs "Face_Verification_Test_Set": -"verification_images": containing 10,051 images, a subset of the whole test set, randomly sampled to build 5,320 positive and 5,320 negative pairs -"positive_pairs_names.mat": 5320_by_2 cell specifying the image pairs of 5,320 positive pairs -"negative_pairs_names.mat": 5320_by_2 cell specifying the image pairs of 5,320 negative pairs # ======================== Evaluation Instruction ========================== # *** Open-Set Face Identification Evaluation ("Face_Identification_Evaluation") *** 1. Extract features of "gallery" images according to the order defined by "gallery_img_ID_pairs.mat", put them in a matrix called "gallery_feature_map" ([image_number]_by_[feature_dimension]), and save the matrix in a mat file named "gallery.mat" 2. Extract features of "mated_pr
03-10
<think>我们正在讨论Linux内核中的位操作函数,特别是set_bit函数。根据引用内容,我们可以总结如下: 1. set_bit函数用于设置一个特定位(设置为1)。 2. 它有两种变体:原子操作版本(set_bit)非原子操作版本(__set_bit)。 3. 这些函数在设备驱动程序中很常见,特别是在输入设备(如触摸屏)的初始化中(如引用[2]所示)。 下面我将详细解释set_bit函数的作用、实现细节以及使用方法。 ### 1. set_bit函数的作用 在Linux内核中,set_bit函数用于将某个内存地址中的特定位(bit)设置为1。其函数原型如下: ```c void set_bit(int nr, volatile unsigned long *addr); ``` - `nr`:要设置的位的序号(从0开始计数)。 - `addr`:指向要设置位的内存地址的指针。 例如,如果我们想设置一个unsigned long类型变量`data`的第3位,可以这样调用: ```c set_bit(3, &data); ``` ### 2. 原子操作与非原子操作 Linux内核提供了两套位操作函数: - **原子操作**:`set_bit`、`clear_bit`、`test_and_set_bit`等,这些函数在执行位操作时是原子性的,不会被中断打断,适用于多核或多线程环境。 - **非原子操作**:`__set_bit`、`__clear_bit`等,这些函数不保证原子性,执行效率更高,但只能在确保不会发生并发访问的上下文中使用(例如,在中断被禁用的情况下)。 ### 3. 实现细节 根据引用[4],非原子版本的`__set_bit`实现如下: ```c static inline void __set_bit(int nr, volatile unsigned long *addr) { unsigned long mask = BIT_MASK(nr); unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); *p |= mask; } ``` 其中: - `BIT_MASK(nr)`:创建一个掩码,该掩码只有第`nr`位为1,其余位为0。例如,`nr=3`时,掩码为`0x00000008`(32位系统)或`0x0000000000000008`(64位系统)。 - `BIT_WORD(nr)`:计算包含第`nr`位的字(word)在数组中的索引。在32位系统中,每个字为32位(4字节);在64位系统中,每个字为64位(8字节)。因此,`BIT_WORD(nr)`等于`nr / BITS_PER_LONG`(其中`BITS_PER_LONG`为32或64)。 - `p`:指向包含目标位的字(word)的指针。 - `*p |= mask`:将目标位置1,其他位保持不变。 原子操作版本`set_bit`的实现依赖于具体的体系结构,通常使用特殊的原子指令(如x86的`bts`指令)来实现。其核心是确保在设置位的过程中不会被其他处理器中断。 ### 4. 使用方法 在设备驱动程序中,我们经常使用`set_bit`来设置设备支持的事件类型属性。以输入设备(如触摸屏)为例(引用[2]): ```c __set_bit(EV_KEY, input_dev->evbit); // 支持按键事件 __set_bit(EV_ABS, input_dev->evbit); // 支持绝对坐标事件(如触摸位置) __set_bit(BTN_TOUCH, input_dev->keybit); // 支持触摸按键 __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); // 设备为直接输入设备(如触摸屏) ``` 这里使用了非原子版本`__set_bit`,因为在设备初始化过程中,通常不会有并发访问的问题(设备尚未注册到系统中)。 ### 5. 原子操作函数`test_and_set_bit` 引用[3]提到了另一个原子操作函数`test_and_set_bit`,该函数设置位并返回该位之前的值: ```c static inline int test_and_set_bit(int nr, unsigned long *addr) { unsigned long mask = BIT_MASK(nr); unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); unsigned long old = *p; *p = old | mask; // 设置位 return (old & mask) != 0; // 返回之前的值 } ``` 这个函数常用于实现锁机制,例如: ```c while (test_and_set_bit(0, &lock) != 0) ; // 自旋等待 ``` ### 6. 总结 - `set_bit`:原子设置位。 - `__set_bit`:非原子设置位,效率更高,但需确保无并发访问。 - 在设备驱动中,常用这些函数来设置设备的能力位图(如事件类型、按键类型等)。 - 原子操作版本用于可能被并发访问的场景,非原子版本用于安全的上下文(如初始化)。 ### 相关问题 1. 在Linux内核中,`clear_bit`函数如何实现? 2. 如何在驱动程序中检测某个位是否被设置? 3. 原子位操作函数在多核系统中如何保证原子性? 4. 在设备驱动中,除了`set_bit`,还有哪些常用的位操作函数? [^1]: 非原子位清除函数`__clear_bit`的实现与`__set_bit`类似 [^2]: 输入设备驱动中设置事件类型的示例 [^3]: `test_and_set_bit`函数的实现与用途 [^4]: `__set_bit`函数的实现细节</think>### Linux 内核中 `set_bit` 函数详解 #### 1. **核心作用** `set_bit` 函数用于**原子性地设置内存中特定位的值(置为 1)**,其函数原型为: ```c void set_bit(int nr, volatile unsigned long *addr); ``` - **`nr`**: 目标位的序号(从 0 开始计数) - **`addr`**: 目标内存地址的指针 - **原子性**: 在多核/多线程环境下确保操作不可分割(避免竞态条件) #### 2. **实现原理** 以 x86 架构为例(源码见 `arch/x86/include/asm/bitops.h`): ```c static __always_inline void set_bit(long nr, volatile unsigned long *addr) { asm volatile("lock; bts %1,%0" : "+m" (*addr) : "Ir" (nr) : "memory"); } ``` - **`lock`**: 指令前缀,锁定内存总线保证原子性 - **`bts`**: 汇编指令(Bit Test and Set),将 `nr` 位设为 1 并返回原值 - **内存屏障**: `"memory"` 约束防止编译器重排序 #### 3. **非原子版本 `__set_bit`** 用于无需原子性的场景(如初始化),实现更简单[^4]: ```c static inline void __set_bit(int nr, volatile unsigned long *addr) { unsigned long mask = BIT_MASK(nr); unsigned long *p = addr + BIT_WORD(nr); *p |= mask; // 直接按位或操作 } ``` - `BIT_MASK(nr)`: 生成位掩码(如 `nr=3` → `0x00000008`) - `BIT_WORD(nr)`: 计算目标位所在长字偏移(`nr / 64`) #### 4. **典型应用场景** ##### (1) 输入设备驱动初始化(如触摸屏) ```c // 设置输入设备支持的事件类型 __set_bit(EV_KEY, input_dev->evbit); // 支持按键事件 __set_bit(EV_ABS, input_dev->evbit); // 支持绝对坐标事件 __set_bit(BTN_TOUCH, input_dev->keybit); // 支持触摸事件 __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); // 直接输入设备[^2] ``` ##### (2) 锁实现 ```c // 使用 test_and_set_bit 实现自旋锁 void spin_lock(atomic_t *lock) { while (test_and_set_bit(0, lock)) // 原子性测试并置位 cpu_relax(); // 忙等待 } ``` #### 5. **原子性 vs 非原子性选择** | **函数** | **原子性** | **使用场景** | **性能影响** | |-------------------|------------|----------------------------------|-------------------| | `set_bit` | 是 | 多核共享数据、中断上下文 | 较高(锁总线) | | `__set_bit` | 否 | 单线程初始化、局部变量操作 | 极低 | | `test_and_set_bit`| 是 | 锁实现、状态标志检测 | 中等(返回原值) | #### 6. **关键衍生函数** - **`clear_bit`**: 原子性清除位(置 0) - **`test_bit`**: 检查位是否置 1 - **`test_and_set_bit`**: 原子性置位并返回原值(锁机制核心)[^3] ```c int old_value = test_and_set_bit(3, &flags); // 置位第3位并返回旧值 ``` ### 常见问题解答 1. **为什么需要 `__set_bit`?** 在单线程初始化阶段(如 `probe` 函数),无需原子性开销,直接位操作效率更高[^4]。 2. **如何安全修改多核共享的位图?** 必须使用 `set_bit/clear_bit` 系列函数,避免使用 `__set_bit`(可能引发数据竞争)。 3. **`test_and_set_bit` 的返回值意义?** 返回目标位操作前的值: - 返回 `1` → 该位原先已置 1 - 返回 `0` → 该位原先为 0 常用于实现自旋锁(返回 0 表示获取锁成功)[^3]。 4. **位操作中的 `volatile` 作用?** 禁止编译器优化内存访问,确保每次操作都直接读写内存(对硬件寄存器操作关键)。 ### 相关问题 1. `clear_bit` `__clear_bit` 的实现有何区别? 2. 如何在内核中安全地遍历位图? 3. `test_and_set_bit` 在自旋锁中如何避免死锁? 4. 在 ARM 架构下 `set_bit` 的实现有何不同? [^1]: 非原子位清除函数 `__clear_bit` 的实现与 `__set_bit` 类似 [^2]: 输入设备驱动中设置事件类型的示例 [^3]: `test_and_set_bit` 函数的实现与用途 [^4]: `__set_bit` 函数的实现细节
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值