视网膜算法

视网膜

首先我们看看视网膜的刨面图,视网膜本身是分了10层,色素上皮层是视网膜的表层,自下而上逐渐深入。

视网膜负责接受光刺激的区域叫感受野,感受野能映射到细胞的输出,而这个输出过程需要进行一次卷积运算,也就是输出需要卷积DOG算子。我们介绍一下DOG算子。DOG模型的本质上是一个二维高斯分布,我们可以写作:
$$
DOG(x)=a_cG(\bar x;\delta _c)-a_sG(\bar x;\delta _s)
$$
为了提高识别精度,视网膜上需要存在拮抗作用的感受野,所以DOG有两种类型,也就是ON和OFF光感受,两者相互拮抗,公式的区别只有一个负号。

首先感受光的是视锥细胞和视杆细胞,前者因为形状的独特性,可以感受颜色。后者因为深度原因可以感受亮度。同时视网膜的光感受器的位置主要集中在中央凹,也就是视轴处。

1

视网膜是如何感受到光的呢?这里有一个过程叫做光转导(phototransduction),这是将外界光能(或光信息)转化为电信号的化学过程,而可以进行光转导的细胞,正是我们上期文章中提到的位于视网膜最表层的光感受器细胞,也正因如此,我们的世界才拥有了色彩。在了解光转导之前,我们先来了解一下光感受器细胞。

光感受器细胞可以进行光转导,在细胞的外部(outer segments)布满了可吸收光且可再生的视色素(visual pigments)。大体上,光感受器细胞分为视杆细胞(rods)视锥细胞(cones)。像它们的名字一样,在显微镜下,视杆细胞的形状就像一根杆,而视锥细胞的形状就像一个锥。我们先来比较一下它们的相同点:除外形外,视锥细胞与视杆细胞在内部结构上是非常相似的。它们均有一层一层的盘(disks)(如图),这里的盘(disks)的化学本质是磷脂分子层,在每个光感受器中都有上千层。在“盘”的表面附着着一些蛋白质,在视杆细胞“盘”上的蛋白质被称为视紫红质(rhodopsine),而在视锥细胞“盘”上的蛋白质被称为视光蛋白(photopsin)。这些蛋白质可以吸收光,并启动一系列光转导的反应。

2

尽管是一类细胞,视杆细胞和视锥细胞的区别还是非常大的。从数量上讲,人的视网膜中约有0.9~1.2亿个视杆细胞而视锥细胞只有400~600万。从位置上讲,视杆细胞分布在除中央凹(fovea)之外的其他区域,而视锥细胞则聚集于中央凹。从对光的敏感度上讲,视杆细胞对光十分敏感,而视锥细胞却没有那么敏感。事实上,视杆细胞的对光的敏感度约为视锥细胞的1000倍,因此,视杆细胞主要负责黑白视觉的产生,而视锥细胞主要负责色彩的产生。视锥细胞分为三种,分别吸收不同波长的光:长波视锥细胞(L cones)约占60%,主要吸收红光;中波视锥细胞(M cones)约占30%,主要吸收绿光;短波视锥细胞(S cones)约占10%,主要吸收蓝光。

3

使用频率作为概率,进行数学估计模型,这样我们就有思路了:

视锥细胞的近似方程:

$$
R_{rod}(r,g,b)=\frac{0.3r+0.6g+0.1b}{255}
$$

视杆细胞的近似方程

$$
R_{cone}(r,g,b)=\frac{R(r)^2+R(g)^2+R(b)^2}{R(r)+R(g)+R(b)}
$$

其中:
$$
R(\lambda)=-a(\lambda-F)+c
$$
a为比例系数,F为敏感度,c为常数,其中当F=1/6、1/2、5/6对应的就是蓝敏,绿敏和红敏细胞。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <iostream>
#include "opencv2/opencv.hpp"

using namespace std;
using namespace cv;

int Rod(int r,int g,int b){
return (0.3*r + 0.6 * g + 0.1*b)/255;
}

double R(double F,double lambda){
return -0.2 * (lambda-F)+0.2;
}

int R_cone(double F,int r,int g,int b){
double up = R(F,r) * R(F,r) + R(F,g) * R(F,g) + R(F,b)* R(F,b);
return up/(R(F,r) + R(F,g) + R(F,b));
}

int main() {
cv::Mat img,cone,rod;
img = cv::imread("C://Users//28211//Desktop//e.jpg");
cone = cv::imread("C://Users//28211//Desktop//e.jpg");
rod = cv::imread("C://Users//28211//Desktop//e.jpg");
for(int y = 0;y < img.rows;y++)
for (int x = 0; x < img.cols; x++) {
Vec3b &img_p = img.at<Vec3b>(x, y);
Vec3b &cone_p = cone.at<Vec3b>(x, y);
cone_p[0] = R_cone(255/6,img_p[0],img_p[1],img_p[2]);
cone_p[1] = R_cone(255/2,img_p[0],img_p[1],img_p[2]);
cone_p[2] = R_cone(255*5/6,img_p[0],img_p[1],img_p[2]);
cone.at<Vec3b>(Point(x,y)) = cone_p;

Vec3b &rod_p = rod.at<Vec3b>(x, y);
rod_p[0] = Rod(img_p[0],img_p[1],img_p[2]);
rod_p[1] = Rod(img_p[0],img_p[1],img_p[2]);
rod_p[2] = Rod(img_p[0],img_p[1],img_p[2]);
rod.at<Vec3b>(Point(x,y)) = rod_p;
}
cv::imshow("Cone",cone);
cv::imshow("rod",rod);
cv::waitKey();
return 0;
}

总结

本期博文通过一些医学知识为计算机视觉引入了一种新的边缘检测方式,即:视网膜算法,这种算法的精度超过了普通算法,但是运行速度慢了许多,不过为更高效的视觉提供了一个新的思路。


视网膜算法
https://blog.minloha.cn/posts/091712833cd1a82023031726.html
作者
Minloha
发布于
2023年3月17日
更新于
2024年4月8日
许可协议