发明内容
水下图像中的金枪鱼的自动识别是一个复杂的问题。必须克服不同鱼的重叠、水体混浊、光照不均导致的过分割等难题。采集到的视频中的不同金枪鱼具有不同的形状、大小和游动方向,因此,需要不受以上变化影响的鲁棒性强的金枪鱼检测方法。针对现有金枪鱼计数困难的技术问题,提供一种基于自适应鱼体弯曲模型的金枪鱼识别方法。
为解决上述技术问题,本发明所采用的技术方案如下:
一种基于自适应鱼体弯曲模型的金枪鱼识别方法,步骤如下:
S1,采集实际条件下金枪鱼的水下图像并预处理。
S1.1,使用安装在金枪鱼转移连接网接口处的摄像机获取视频信息。
所述摄像机包括摄像机A和摄像机B,摄像机A和摄像机B均安装在一个圆形平台上,圆形平台位于养殖笼底部并由浮标提供浮力;且摄像机A和摄像机B的镜头均朝向水面;摄像机A以20f/s获取视频AR20,摄像机B以30f/s获取视频BR30。
S1.2,对视频信息进行采样获得若干视频帧图像Ft。
S1.2.1,对摄像机A以20f/s获取的视频AR20通过10选1进行采样得到视频采样图像AR20’。
S1.2.2,对摄像机B以30f/s获取的视频BR30通过10选1进行采样得到视频采样图像BR30’。
S1.2.3,从视频采样帧图像AR20’和视频采样图像BR30’中获得若干个视频帧图像Ft,并将视频帧图像Ft变为RGB图像Ft’。
S1.3,对各视频帧图像分别进行图像处理,将各视频帧图像分别分割为不同的候选斑块;所述图像处理包括图像灰度化和图像二值化。
S1.3.1,图像灰度化。
采用平均值法,将彩色图像Ft’转换为灰度图像Grayt,转换公式为:
Grayt(x,y)=(RFt(x,y)+GFt(x,y)+BFt(x,y))/3;
其中,x、y分别表示图像的行坐标值和列坐标值;RFt(x,y)、GFt(x,y)、BFt(x,y)分别表示RGB图像Ft’的(x,y)处的R、G、B通道的值;Grayt(x,y)表示灰度图像Grayt在(x,y)处的灰度值。
S1.3.2,图像二值化;
S1.3.2.1,采用局部阈值法将灰度图像Grayt的所有灰度值Grayt(x,y)二值化得到二值化图像Bint。
S1.3.2.1.1,计算灰度图像Grayt的像素点(x,y)处的局部领域的灰度值的均值Mt,xy,计算公式为:
其中,E×F是局部邻域的大小;i、j分别表示灰度图像Grayt的行坐标值和列坐标值;
对于边界像素点的邻域问题,图像边界之外的像素值通过镜像获得。
S1.3.2.1.2,得到二值化图像Bint;
将均值Mt,xy作为阈值用于判断灰度图像Grayt的像素点(x,y)为前景或背景;如果像素点Grayt(x,y)的灰度值小于均值Mt,xy,那么将像素点设定为前景,取值为0,否则设定为背景,取值为1,从而得到二值化图像Bint,公式为:
S1.3.2.2,对二值化图像Bint取反得到二值化图像Binrt;
在二值化图像Bint中斑块区域的值为0,呈现黑色;背景区域的值为1,呈现白色;
对二值化图像Bint取反,将像素值为0的改为1,像素值为1的改为0,得到二值化图像Binrt;
S1.3.2.3,对二值化图像Binrt进行填充得到二值化图像Binrft;
采用Matlab中的imfill函数对二值化图像Binrt进行填充,得到填充后的二值化图像Binrft,填充公式为:
Binrft=imfill(Binrt,'holes');
S1.3.2.4,平滑二值化图像Binrt,得到二值化图像Binrfct;
采用Matlab中的imclose函数将对二值化图像Binrft进行形态学处理中的闭运算操作,平滑二值化图像Binrft中的各个斑块的轮廓并且将紧邻的斑块合并得到闭运算后的二值化图像Binrfct,具体的操作为:
Binrfct=imclose(Binrft,se);
其中,se表示半径为D的圆形结构元素,创建函数为:
se=strel('disk',D);
含义为创建一个半径为D的圆形结构元素,disk表示圆形形状。
S2,删除二值化图像Binrfct中包含图像边界的连通区域,得到图像Bcbt。
采用matlab中的函数imclearborder对二值化图像Binrfct进行边界对象抑制,删除包含图像边界的连通区域后得到图像Bcbt。
S3,标记图像Bcbt中的连通区域。
采用Matlab中连通区域标记函数bwlabel对图像Bcbt进行连通区域的标记:
[JLt,NUMt]=bwlabel(Bcbt,conn);
其中,NUMt表示图像Bcbt中连通区域的数量,即斑块的数量;JLt表示和图像Bcbt大小相同的矩阵,JLt矩阵包含了标记了图像Bcbt中每个连通区域的类别标签,标签的值为1,2,…,NUMt;conn表示是按conn邻域寻找连通区域。
S4,去除图像Bcbt中无用的连通区域,得到图形Bcbt’。
S4.1,得到图像Bcbt中各连通区域的像素总数。
采用Matlab中regionprops函数获得图像Bcbt中各连通区域的像素总数;
statust=regionprops(JLt,'Area');
设定scxy的取值范围为1~NUMt,则statust(scxy,1)表示第scxy个连通区域的面积(各个连通区域的像素总数也叫各个连通区域的面积)。
S4.2,将各连通区域的面积与设定值比较,若小于设定值则该连通区域去除,得到图形Bcbt’。
依次检测各个连通区域的面积,如果第scxy个连通区域的面积小于设定值,则将与矩阵JLt中值为scxy的元素的位置相同的Bcbt处的像素值置0,从而去除了图像Bcbt中的面积小于设定值的斑块。
S5,提取图形Bcbt’中各连通区域得到鱼体的候选斑块。
采用Matlab中连通区域标记函数bwlabel,标记图像Bcbt’中的连通区域得到鱼体的候选斑块:
[SJLt,SNUMt]=bwlabel(Bcbt’,conn);
SNUMt表示图像Bcbt’中连通区域的数量,即候选斑块的数量;SJLt表示和图像Bcbt’大小相同的矩阵,SJLt矩阵包含了标记了图像Bcbt’中每个连通区域的类别标签,这些标签的值为1,2,…,SNUMt。
设定lti的值为1~SNUMt,则设定SJLFt,lti=SJLt,将SJLFt,lti中的值为0的元素保留,值为lti的元素置1,其它值的元素置0,则分别提取出了图像Bcbt的第lti个连通区域。
S6,提取各候选斑块的骨架。
S6.1,对各个候选斑块进行骨架提取。
采用Matlab中的bwmorph函数对各个候选斑块进行形态学操作,其中的'skel'属性是进行骨架提取,同时保持骨架不发生断裂;应用形态学操作xn次,直到各连通区域的骨架不再发生变化为止:
gujiat,lti=bwmorph(SJLFt,lti,'skel',xn);
S6.2,去除各骨架的毛刺;
采用Matlab中的bwmorph函数中包含'spur'属性,去除小的分支:
gujiaqucit,lti=bwmorph(gujiat,lti,'spur',xn);
S7,获得提取骨架的端点数并再次筛选候选斑块。
S7.1,获得骨架的端点;
采用Matlab中的bwmorph函数中包含'endpoints'属性,用于查找骨架的端点;所述端点包含金枪鱼的头部端点、胸鳍两侧的端点;由于尾鳍存在多种变化,还会查找到尾鳍的端点,当尾部只有一个端点时,可将其作为尾部端点;
duandiant,lti=bwmorph(gujiaqucit,lti,'endpoints')。
S7.2,根据步骤S7.1中获得的端点数筛选候选斑块。
如果候选斑块的端点数量小于4或者大于5,则将该候选斑块排除,并判定为坏鱼。
S8,比较候选斑块的端点数与设定值大小,若候选斑块的端点数量等于4时进行步骤S9-S12,若候选斑块的端点数量等于5时进行步骤S13-S15。
S9,确定候选斑块的头部端点和尾部端点,得到鱼体头部坐标(Sx,Sy)。
按照从上到下,从左至右的顺序,候选斑块中提取到四个端点。
S9.1,计算两两端点之间的距离。
S9.2,确定头部端点和尾部端点。
相互比较各距离,并选择距离最大的两个端点作为头部端点或尾部端点;并在剩余两个端点中择一作为胸鳍端点,并比较该胸鳍端点距离头部端点或尾部端点的距离,并选择距离大的端点作为尾部端点,另一端点为头部端点,则鱼体头部坐标(Sx,Sy)就是头部端点的坐标。
S10,获得金枪鱼脊柱的长度l。
S10.1,剔除金枪鱼骨架中表示胸鳍的两个支径,得到骨架gujiaqucitizhit,lti。
S10.1.1,以胸鳍端点为中心点Pcenter。
S10.1.2,搜索中心点Pcenter的H邻域。
S10.1.3,若H邻域内仅有1个像素点Pnext的像素为1,则进行步骤S10.1.4;若H邻域内至少有2个像素点Pnext的像素为1,则进行步骤S10.1.5。
S10.1.4,将当前中心点Pcenter的像素值置为0,并将像素点Pnext作为新的中心点Pcenter,并重复步骤S10.1.2-S10.1.3。
S10.1.5,将中心点Pcenter删除,实现胸鳍端点支径的剔除。
S10.1.6,重复步骤S10.1.1-S10.1.5,直至两个胸鳍端点支径都被剔除,得到骨架gujiaqucitizhit,lti。
S10.2,计算金枪鱼脊柱的长度l。
S10.2.1,获得骨架gujiaqucitizhit,lti主径的周长为LOBt,lti。
采用Matlab中regionprops函数,得到金枪鱼的骨架的主径的周长为LOBt,lti:
LOBt,lti=regionprops(gujiaqucitizhit,lti,'perimeter');
S10.2.2,将周长LOBt,lti除以2就得到金枪鱼脊柱的长度l:
lt,lti=LOBt,lti/2;
S11,计算倾斜角度α。
S11.1,从头部端点(Sx,Sy)开始,查找H邻域内的像素值为1的点。
S11.2,以找到的像素为1的点为中心,再次查找H邻域内的像素值为1的点。
S11.3,重复步骤S11.2,直至循环结束,所述循环结束条件是循环到第30个点,因为从头部端点开始,沿着脊柱行走30个点,基本上是一条直线,因为金枪鱼的头部那段的脊柱是直的,不会弯曲,将30个点组成的线段近似看成直线,该直线和头部那段脊柱的直线的角度就是鱼体的弯曲角度,如图6所示。
S11.4,将头部端点及查找到的像素为1的点依次存入二维数组Head。
S11.5,根据二维数组Head进行直线拟合。
采用Matlab中的polyfit函数进行直线拟合,拟合公式为:
Headp=polyfit(Head(1,:),Head(2,:),1)
式中,Headp(1)为考虑到鱼头朝向的头部的脊柱段所拟合成的直线的斜率;Head(2,:)为头部的脊柱点所构成的二维数组中的Y坐标。
S11.6,根据步骤S11.5得到倾斜角度α。
S11.6.1,得到头部的脊柱点所构成的二维数组中的Y坐标的最大值max(Head(2,:))。
S11.6.2,比较max(Head(2,:))与Sy的大小,若max(Head(2,:))等于Sy,则鱼体的倾斜角度α为:
αt,lti=arctan(Headp(1));
否则,鱼体的倾斜角度α为:
αt,lti=arctan(-Headp(1))
S12,计算弯曲角度θ。
S12.1,从尾部端点开始,查找H邻域内的像素值为1的点。
S12.2,以像素值为1的点为中心,再次查找H邻域内的像素值为1的点。
S12.3,重复步骤S12.2,直至循环结束,所述循环结束条件是循环到第30个点,因为从尾部端点开始,将尾部30个点组成的线段近似看成直线,该直线和头部脊柱的那段直线构成的角度就是鱼体的弯曲角度,如图6所示。
S12.4,将尾部端点及查找到的像素值为1的点依次存入二维数组Teal。
S12.5,根据二维数组Teal进行直线拟合。
采用Matlab中的polyfit函数进行直线拟合,拟合公式为:
Tealp=polyfit(Teal(1,:),Teal(2,:),1)
其中,Tealp(1)为尾部的脊柱所拟合成的直线的斜率。
S12.6,根据步骤S12.5得到弯曲角度θ:
θt,lti=arctan((Headp(1)-Tealp(1))/(1-Headp(1)*Tealp(1)))
S13,确定候选斑块的头部端点,得到鱼体头部坐标(Sx,Sy),并获得鱼体脊柱的长度l。
从上到下,从左到右的顺序,候选斑块提取到5个端点。
S13.1,计算两两端点之间的距离。
S13.2,确定头部端点。
相互比较各距离,并选择距离最小的两个端点作为尾鳍端点JC和尾鳍端点JD;以尾鳍端点JC或尾鳍端点JD为出发点,分别比较尾鳍端点JC或尾鳍端点JD与剩余三个端点的距离,选择距离最大值所对应的端点为头部端点JA;剩余的两个端点就是胸鳍端点JB和胸鳍端点JE。
S13.3,获得金枪鱼脊柱的长度l。
S13.3.1,获得金枪鱼骨架的交叉点。
S13.3.1.1,采用Matlab中的bwmorph函数中查找骨架的交叉点,具体为:
jiaochadiant,lti=bwmorph(gujiaqucit,lti,'branchpoints')
S13.3.1.2,计算jiaochadiant,lti中的两个交叉点到头部端点JA的距离,并将距离值较小的交叉点作为胸鳍和脊柱的交叉点PF,将距离值较大的交叉点作为尾鳍和脊柱的交叉点TF。
S13.3.2,剔除金枪鱼骨架中表示胸鳍的两个支径和两个尾鳍的两个支径,得到骨架gujiaqucitizhit,lti。
S13.3.2.1,以胸鳍端点为中心点Pcenter。
S13.3.2.2,搜索中心点Pcenter的H邻域。
S13.3.2.3,若H邻域内仅有1个像素点Pnext的像素为1,则进行步骤S13.3.2.4;若H邻域内至少有2个像素点Pnext的像素为1,则进行步骤S13.3.2.5。
S13.3.2.4,将当前中心点Pcenter的像素值置为0,并将像素点Pnext作为新的中心点Pcenter,并重复步骤S13.3.2.2-S13.3.2.3。
S13.3.2.5,将中心点Pcenter删除,实现胸鳍端点支径的剔除。
S13.3.2.6,重复步骤S13.3.2.1-S13.3.2.5,直至两个胸鳍端点支径都被剔除。
S13.3.2.7,以尾鳍端点为中心点Pcenter,重复步骤S13.3.2.2-S13.3.2.6,直至两个包含尾鳍端点支径都被剔除,得到骨架gujiaqucitizhit,lti。
S13.3.3,计算金枪鱼脊柱的长度l。
S13.3.3.1,获得骨架gujiaqucitizhit,lti主径的周长为LOBt,lti。
采用Matlab中regionprops函数,得到金枪鱼的骨架的主径的周长为LOBt,lti:
LOBt,lti=regionprops(gujiaqucitizhit,lti,'perimeter')
S13.3.3.2,将周长LOBt,lti除以2就得到金枪鱼脊柱的长度l:
lt,lti=LOBt,lti/2
S14,计算倾斜角度α。
S14.1,从头部端点(Sx,Sy)开始,查找H邻域内的像素值为1的点。
S14.2,以找到的像素为1的点为中心,再次查找H邻域内的像素值为1的点。
S14.3,重复步骤S14.2,直至循环结束,所述循环结束条件是循环到第30个点,因为从头部端点开始,沿着脊柱行走30个点,基本上是一条直线,因为金枪鱼的头部那段的脊柱是直的,不会弯曲,将30个点组成的线段近似看成直线,该直线和头部脊柱的那段直线构成的角度就是鱼体的弯曲角度,如图6所示。
S14.4,将头部端点及查找到的像素为1的点依次存入二维数组Head。
S14.5,根据二维数组Head进行直线拟合。
采用Matlab中的polyfit函数进行直线拟合,拟合公式为:
Headp=polyfit(Head(1,:),Head(2,:),1);
式中,Headp(1)为考虑到鱼头朝向的头部的脊柱段所拟合成的直线的斜率;Head(2,:)为头部的脊柱点所构成的二维数组中的Y坐标。
S14.6,根据步骤S14.5得到倾斜角度α。
S14.6.1,得到头部的脊柱点所构成的二维数组中的Y坐标的最大值max(Head(2,:))。
S14.6.2,比较max(Head(2,:))与Sy的大小,若max(Head(2,:))等于Sy,则鱼体的倾斜角度α为:
αt,lti=arctan(Headp(1));
否则,鱼体的倾斜角度α为:
αt,lti=arctan(-Headp(1))
S15,计算弯曲角度θ。
S15.1,从交叉点TF开始,查找H邻域内的像素值为1的点。
S15.2,以像素值为1的点为中心,再次查找H邻域内的像素值为1的点。
S15.3,重复步骤S15.2,直至循环结束,所述循环结束条件是循环到第30个点,因为从尾部端点开始,将尾部30个点组成的线段近似看成直线,该直线和头部脊柱的那段直线构成的角度就是鱼体的弯曲角度。
S15.4,将交叉点TF及查找到的像素值为1的点依次存入二维数组Teal。
S15.5,根据二维数组Teal进行直线拟合。
采用Matlab中的polyfit函数进行直线拟合,拟合公式为:
Tealp=polyfit(Teal(1,:),Teal(2,:),1);
其中,Tealp(1)为尾部的脊柱所拟合成的直线的斜率。
S15.6,根据步骤S15.5得到弯曲角度θ:
θt,lti=arctan((Headp(1)-Tealp(1))/(1-Headp(1)*Tealp(1)))
S16,根据步骤S9-S12或S13-S15构造候选斑块的初始模型M:
M=(Sx、Sy、l、α、θ);
S17,获取各候选斑块的轮廓上的边界点坐标。
采用matlab中的bwboundaries函数获取各个候选斑块的轮廓Bdt,lti,Bdt,lti存储的是候选斑块的边界点的坐标;
Bdt,lti=bwboundaries(SJLFt,lti,conn);
SJLFt,lti为第t个图像的第lti个候选斑块。
S18,计算初始模型M中的参考点和标记点的坐标,并计算当前候选斑块和与其对应的初始模型M之间的拟合误差指数FEI。
S18.1,计算初始模型M中的参考点坐标和标记点坐标。
S18.1.1,计算参考点vj的坐标(x’j v,y’j v):
其中,j=1,2,…,19,x0 v=0,y0 v=0;dθj为脊柱上的参考点处的局部弯曲角度,且dθj=Δθj。
S18.1.2,计算标记点ki的坐标(xi’k,yi’k)。
S18.1.2.1,右侧轮廓标记点坐标计算公式为:
其中,i=1,2,…,19;S
l为脊柱均分的长度;C
i为参考点到与它对应的右侧轮廓标记点的距离系数,
为参考点在X轴的坐标;
为参考点在Y轴的坐标。
S18.1.2.2,左侧轮廓标记点坐标计算公式为:
其中,i=21,…,39;Ci-20为参考点到与它对应的左侧轮廓标记点的距离系数。
S18.2,计算候选斑块建立的初始模型的标记点到该斑块的边界的最近距离dt,lti(ki,Bdt,lti,i)。
根据5个模型参数建立金枪鱼模型的轮廓,以轮廓上的标记点ki为中心,沿着线段kiVi的方向,向标记点ki的两侧各延伸l/64,从而构成基于标记点ki的探测线,如果该探测线与候选斑块的边界的交点为pbod,则初始模型的标记点与候选斑块的边界点匹配成功,则线段kipbod的长度就是dt,lti(ki,Bdt,lti,i)。
S18.3,根据步骤S18.1-S18.2,计算候选斑块与初始模型的拟合误差指数FEI。
其中,lt,lti是模型的脊柱长度,m是与候选斑块边界点成功匹配的初始模型M的标记点的数量;dt,lti(ki,Bdt,lti,i)是根据候选斑块建立的初始模型的标记点到该斑块的边界点的最近距离。
S19,根据候选斑块的边界点和M的标记点相匹配的数量以及拟合误差指数FEI,判断候选斑块是否为一条完整的金枪鱼。
拟合误差指数FEI为0,则表示候选斑块和对应的初始模型M之间的完美契合;如果找到至少35个候选斑块的边界点与M的标记点相匹配,并且拟合误差指数FEI≤2.23,则判定候选斑块是一条完整的金枪鱼。
本发明通过搭建视频图像的采集平台;并对获取的自然水下的视频帧进行采样,由于相邻帧之间的采集时间较短,不能提供显着的差异,需要通过采样来减小数据冗余;然后将采样后得到的帧进行图像处理(图像灰度化及图像二值化),分割为不同的斑块用于后续判断是否为单条完整的好鱼;接着去除不满足要求的斑块(接触图像的边界的斑块,以及比所设定值还小的斑块),然后计算剩余的候选斑块的特征,获得自适应鱼体弯曲的初始模型M;再计算候选斑块的边界点和与其对应的初始模型M的标记点的匹配情况,如果找到至少35组边界点和标记点相互匹配,并且拟合误差指数FEI≤2.23,则判定候选斑块为好鱼;不满足以上条件则设定该斑块为坏鱼(可能是金枪鱼鱼体的一部分或者候选斑块为不同的金枪鱼的鱼体重叠部分)。本发明无需人工干预,自动获得金枪鱼的形状、大小、游动方向(头部朝向)和弯曲姿态,可识别运动中的金枪鱼,克服分割不准确的难题,并有助于自动计算金枪鱼的生物量,可以采用机器视觉系统及基于自适应鱼体弯曲模型的有用信息来解决渔业的自动化的需求,如生物测量、样本计数及估测捕获生物量。本发明具有以下优点:(1)视频图像来自水下的自然环境,无需人工照明,无需提供实验背景。(2)图像可以包含拥挤或重叠的鱼群。(3)全程自动从图像中识别提取单条完整的金枪鱼。(4)在本发明的处理过程中,所有金枪鱼的初始模型M的参数均为自动提取,没有人工干预。(5)金枪鱼的游动方向是未知的,并且本发明自动获得金枪鱼的游动方向(头部朝向)。
具体实施方式
下面将结合本发明实施例中的附图,对本发明实施例中的技术方案进行清楚、完整地描述,显然,所描述的实施例仅仅是本发明一部分实施例,而不是全部的实施例。基于本发明中的实施例,本领域普通技术人员在没有付出创造性劳动前提下所获得的所有其他实施例,都属于本发明保护的范围。
一种基于自适应鱼体弯曲模型的金枪鱼识别方法,步骤如下:
S1,采集实际条件下金枪鱼的水下图像并预处理。
S1.1,使用安装在金枪鱼转移连接网接口处的摄像机获取视频信息。
所述摄像机包括摄像机A和摄像机B,摄像机A和摄像机B均安装在一个直径为50cm的圆形平台上,圆形平台位于养殖笼底部并由浮标提供浮力;且摄像机A和摄像机B的镜头均朝向水面并且视频图像是在晴朗天气采集视频图像从水面以下220cm处获得的,养殖笼包含约400条长度在112cm-226cm长的成年金枪鱼;摄像机A以20f/s获取视频AR20,摄像机B以30f/s获取视频BR30。
采用摄像机获取金枪鱼的视频,具有非接触的优点(应力可能导致金枪鱼死亡),并提供连续、客观和可重复的结果,并且因为金枪鱼在水中自由游动时,鱼体可能处于弯曲状态,这意味着采集到的视频帧中的不同金枪鱼具有不同的形状、大小和游动方向,如图1所示。
S1.2,对视频信息进行采样获得若干视频帧图像Ft。
S1.2.1,对摄像机A以20f/s获取的视频AR20通过10选1进行采样得到视频采样图像AR20’。
S1.2.2,对摄像机B以30f/s获取的视频BR30通过10选1进行采样得到视频采样图像BR30’。
S1.2.3,从视频采样帧图像AR20’和视频采样图像BR30’中获得若干个视频帧图像Ft,并将视频帧图像Ft变为RGB图像Ft’。
具体是在7036(视频AR20的4605个连续帧+视频BR30的2436个连续帧)个视频帧中,采样703帧Ft,t的取值为1~703,将Ft转换为RGB图像进行后续分析。
S1.3,对各视频帧图像分别进行图像处理,将各视频帧图像分别分割为不同的候选斑块;所述图像处理包括图像灰度化和图像二值化。
S1.3.1,图像灰度化。
采用平均值法,将彩色图像Ft’转换为灰度图像Grayt,转换公式为:
Grayt(x,y)=(RFt(x,y)+GFt(x,y)+BFt(x,y))/3;
其中,x、y分别表示图像的行坐标值和列坐标值;RFt(x,y)、GFt(x,y)、BFt(x,y)分别表示RGB图像Ft’的(x,y)处的R、G、B通道的值;Grayt(x,y)表示灰度图像Grayt在(x,y)处的灰度值。
S1.3.2,图像二值化;
S1.3.2.1,采用局部阈值法将灰度图像Grayt的所有灰度值Grayt(x,y)二值化得到二值化图像Bint。
S1.3.2.1.1,计算灰度图像Grayt的像素点(x,y)处的局部领域的灰度值的均值Mt,xy,计算公式为:
其中,E×F是局部邻域的大小,在本实施例中采用的是15×15领域;i、j分别表示灰度图像Grayt的行坐标值和列坐标值;
对于边界像素点的邻域问题,图像边界之外的像素值通过镜像获得。
S1.3.2.1.2,得到二值化图像Bint;
将均值Mt,xy作为阈值用于判断灰度图像Grayt的像素点(x,y)为前景或背景;如果像素点Grayt(x,y)的灰度值小于均值Mt,xy,那么将像素点设定为前景,取值为0,否则设定为背景,取值为1,从而得到二值化图像Bint,公式为:
S1.3.2.2,对二值化图像Bint取反得到二值化图像Binrt;
在二值化图像Bint中斑块区域的值为0,呈现黑色;背景区域的值为1,呈现白色;
对二值化图像Bint取反,将像素值为0的改为1,像素值为1的改为0,得到二值化图像Binrt;
S1.3.2.3,对二值化图像Binrt进行填充得到二值化图像Binrft;
采用Matlab中的imfill函数对二值化图像Binrt进行填充,得到填充后的二值化图像Binrft,填充公式为:
Binrft=imfill(Binrt,'holes');
S1.3.2.4,平滑二值化图像Binrt,得到二值化图像Binrfct;
采用Matlab中的imclose函数将对二值化图像Binrft进行形态学处理中的闭运算操作,平滑二值化图像Binrft中的各个斑块的轮廓并且将紧邻的斑块合并得到闭运算后的二值化图像Binrfct,具体的操作为:
Binrfct=imclose(Binrft,se);
其中,se表示半径为D的圆形结构元素,创建函数为:
se=strel('disk',D);
含义为创建一个半径为D的圆形结构元素,disk表示圆形形状。
通过孔洞填充和形态学中的闭运算操作,解决了前景斑块出现小孔及斑块相互靠近的问题,获得了良好的处理效果。
S2,删除二值化图像Binrfct中包含图像边界的连通区域,得到图像Bcbt。
采用matlab中的函数imclearborder对二值化图像Binrfct进行边界对象抑制,删除包含图像边界的连通区域后得到图像Bcbt。
S3,标记图像Bcbt中的连通区域。
采用Matlab中连通区域标记函数bwlabel对图像Bcbt进行连通区域的标记:
[JLt,NUMt]=bwlabel(Bcbt,conn);
其中,NUMt表示图像Bcbt中连通区域的数量,即斑块的数量;JLt表示和图像Bcbt大小相同的矩阵,JLt矩阵包含了标记了图像Bcbt中每个连通区域的类别标签,标签的值为1,2,…,NUMt;conn表示是按conn邻域寻找连通区域,本发明中采用8邻域,即设定conn为8。
S4,去除图像Bcbt中无用的连通区域,得到图形Bcbt’。
S4.1,得到图像Bcbt中各连通区域的像素总数。
采用Matlab中regionprops函数获得图像Bcbt中各连通区域的像素总数;
statust=regionprops(JLt,'Area');
设定scxy的取值范围为1~NUMt,则statust(scxy,1)表示第scxy个连通区域的面积。
S4.2,将各连通区域的面积与设定值比较,若小于设定值则该连通区域去除,得到图形Bcbt’。
依次将各个连通区域的面积与设定值2200比较,如果第scxy个连通区域的面积小于设定值,则将与矩阵JLt中值为scxy的元素的位置相同的Bcbt处的像素值置0,从而去除了图像Bcbt中的面积小于设定值的斑块。
S5,提取图形Bcbt’中各连通区域得到鱼体的候选斑块。
采用Matlab中连通区域标记函数bwlabel,标记图像Bcbt’中的连通区域得到鱼体的候选斑块:
[SJLt,SNUMt]=bwlabel(Bcbt’,conn);
SNUMt表示图像Bcbt’中连通区域的数量,即候选斑块的数量;SJLt表示和图像Bcbt’大小相同的矩阵,SJLt矩阵包含了标记了图像Bcbt’中每个连通区域的类别标签,这些标签的值为1,2,…,SNUMt。
设定lti的值为1~SNUMt,则设定SJLFt,lti=SJLt,将SJLFt,lti中的值为0的元素保留,值为lti的元素置1,其它值的元素置0,则分别提取出了图像Bcbt的第lti个连通区域。
S6,提取各候选斑块的骨架。
S6.1,对各个候选斑块进行骨架提取。
采用Matlab中的bwmorph函数对各个候选斑块进行形态学操作,其中的'skel'属性是进行骨架提取,同时保持骨架不发生断裂;应用形态学操作xn次,直到各连通区域的骨架不再发生变化为止:
gujiat,lti=bwmorph(SJLFt,lti,'skel',xn);
S6.2,去除各骨架的毛刺;
采用Matlab中的bwmorph函数中包含'spur'属性,去除小的分支:
gujiaqucit,lti=bwmorph(gujiat,lti,'spur',xn);
S7,获得提取骨架的端点数并再次筛选候选斑块。
S7.1,获得骨架的端点;
采用Matlab中的bwmorph函数中包含'endpoints'属性,用于查找骨架的端点;所述端点包含金枪鱼的头部端点、尾部端点以及胸鳍两侧的端点;
duandiant,lti=bwmorph(gujiaqucit,lti,'endpoints')。
S7.2,根据步骤S7.1中获得的端点数筛选候选斑块。
如果候选斑块的端点数量小于4或者大于5,则将该候选斑块排除,并判定为坏鱼。
S8,比较候选斑块的端点数与设定值大小,若候选斑块的端点数量等于4时进行步骤S9-S12,若候选斑块的端点数量等于5时进行步骤S13-S15。
S9,确定候选斑块的头部端点和尾部端点,得到鱼体头部坐标(Sx,Sy)。
按照从上到下,从左至右的顺序,候选斑块中提取到四个端点。
S9.1,计算两两端点之间的距离。
S9.2,确定头部端点和尾部端点。
相互比较各距离,并选择距离最大的两个端点作为头部端点或尾部端点;并在剩余两个端点中择一作为胸鳍端点,并比较该胸鳍端点距离头部端点或尾部端点的距离,并选择距离大的端点作为尾部端点,另一端点为头部端点,则鱼体头部坐标(Sx,Sy)就是头部端点的坐标。
S10,获得金枪鱼脊柱的长度l。
S10.1,剔除金枪鱼骨架中表示胸鳍的两个支径,得到骨架gujiaqucitizhit,lti。
S10.1.1,以胸鳍端点为中心点Pcenter。
S10.1.2,搜索中心点Pcenter的H邻域。
S10.1.3,若H邻域内仅有1个像素点Pnext的像素为1,则进行步骤S10.1.4;若H邻域内至少有2个像素点Pnext的像素为1,则进行步骤S10.1.5。
S10.1.4,将当前中心点Pcenter的像素值置为0,并将像素点Pnext作为新的中心点Pcenter,并重复步骤S10.1.2-S10.1.3。
S10.1.5,将中心点Pcenter删除,实现胸鳍端点支径的剔除。
S10.1.6,重复步骤S10.1.1-S10.1.5,直至两个胸鳍端点支径都被剔除,得到骨架gujiaqucitizhit,lti。
S10.2,计算金枪鱼脊柱的长度l。
S10.2.1,获得骨架gujiaqucitizhit,lti主径的周长为LOBt,lti。
采用Matlab中regionprops函数,得到金枪鱼的骨架的主径的周长为LOBt,lti:
LOBt,lti=regionprops(gujiaqucitizhit,lti,'perimeter')
S10.2.2,将周长LOBt,lti除以2就得到金枪鱼脊柱的长度l:
lt,lti=LOBt,lti/2;
S11,计算倾斜角度α。
S11.1,从头部端点(Sx,Sy)开始,查找H邻域内的像素值为1的点。
S11.2,以找到的像素为1的点为中心,再次查找H邻域内的像素值为1的点。
S11.3,重复步骤S11.2,直至循环结束,所述循环结束条件是循环到第30个点,因为从头部端点开始,沿着脊柱行走30个点,基本上是一条直线,因为金枪鱼的头部那段的脊柱是直的,不会弯曲,将30个点组成的线段近似看成直线,该直线和头部脊柱那段的直线构成的角度就是鱼体的弯曲角度。
S11.4,将头部端点及查找到的像素为1的点依次存入二维数组Head。
S11.5,根据二维数组Head进行直线拟合。
采用Matlab中的polyfit函数进行直线拟合,拟合公式为:
Headp=polyfit(Head(1,:),Head(2,:),1)。
式中,Headp(1)为考虑到鱼头朝向的头部的脊柱段所拟合成的直线的斜率;Head(2,:)为头部的脊柱点所构成的二维数组中的Y坐标。
S11.6,根据步骤S11.5得到倾斜角度α。
S11.6.1,得到头部的脊柱点所构成的二维数组中的Y坐标的最大值max(Head(2,:))。
S11.6.2,比较max(Head(2,:))与Sy的大小,若max(Head(2,:))等于Sy,则鱼体的倾斜角度α为:
αt,lti=arctan(Headp(1));
否则,鱼体的倾斜角度α为:
αt,lti=arctan(-Headp(1))
S12,计算弯曲角度θ。
S12.1,从尾部端点开始,查找H邻域内的像素值为1的点。
S12.2,以像素值为1的点为中心,再次查找H邻域内的像素值为1的点。
S12.3,重复步骤S12.2,直至循环结束,所述循环结束条件是循环到第30个点,因为从尾部端点开始,将尾部30个点组成的线段近似看成直线,该直线和头部脊柱那段的直线构成的角度就是鱼体的弯曲角度。
S12.4,将尾部端点及查找到的像素值为1的点依次存入二维数组Teal。
S12.5,根据二维数组Teal进行直线拟合。
采用Matlab中的polyfit函数进行直线拟合,拟合公式为:
Tealp=polyfit(Teal(1,:),Teal(2,:),1)
其中,Tealp(1)为尾部的脊柱所拟合成的直线的斜率。
S12.6,根据步骤S12.5得到弯曲角度θ:
θt,lti=arctan((Headp(1)-Tealp(1))/(1-Headp(1)*Tealp(1)))
S13,确定候选斑块的头部端点,得到鱼体头部坐标(Sx,Sy),并获得鱼体脊柱的长度l。
从上到下,从左到右的顺序,候选斑块提取到5个端点。
S13.1,计算两两端点之间的距离。
S13.2,确定头部端点。
相互比较各距离,并选择距离最小的两个端点作为尾鳍端点JC和尾鳍端点JD;以尾鳍端点JC或尾鳍端点JD为出发点,分别比较尾鳍端点JC或尾鳍端点JD与剩余三个端点的距离,选择距离最大值所对应的端点为头部端点JA;剩余的两个端点就是胸鳍端点JB和胸鳍端点JE。
S13.3,获得金枪鱼脊柱的长度l。
S13.3.1,获得金枪鱼骨架的交叉点。
S13.3.1.1,采用Matlab中的bwmorph函数中查找骨架的交叉点,具体为:
jiaochadiant,lti=bwmorph(gujiaqucit,lti,'branchpoints')
S13.3.1.2,计算jiaochadiant,lti中的两个交叉点到头部端点JA的距离,并将距离值较小的交叉点作为胸鳍和脊柱的交叉点PF,将距离值较大的交叉点作为尾鳍和脊柱的交叉点TF。
S13.3.2,剔除金枪鱼骨架中表示胸鳍的两个支径和两个尾鳍的两个支径,得到骨架gujiaqucitizhit,lti。
S13.3.2.1,以胸鳍端点为中心点Pcenter。
S13.3.2.2,搜索中心点Pcenter的H邻域。
S13.3.2.3,若H邻域内仅有1个像素点Pnext的像素为1,则进行步骤S13.3.2.4;若H邻域内至少有2个像素点Pnext的像素为1,则进行步骤S13.3.2.5。
S13.3.2.4,将当前中心点Pcenter的像素值置为0,并将像素点Pnext作为新的中心点Pcenter,并重复步骤S13.3.2.2-S13.3.2.3。
S13.3.2.5,将中心点Pcenter删除,实现胸鳍端点支径的剔除。
S13.3.2.6,重复步骤S13.3.2.1-S13.3.2.5,直至两个胸鳍端点支径都被剔除。
S13.3.2.7,以尾鳍端点为中心点Pcenter,重复步骤S13.3.2.2-S13.3.2.6,直至两个包含尾鳍端点的支径都被剔除,得到骨架gujiaqucitizhit,lti。
S13.3.3,计算金枪鱼脊柱的长度l。
S13.3.3.1,获得骨架gujiaqucitizhit,lti主径的周长为LOBt,lti。
采用Matlab中regionprops函数,得到金枪鱼的骨架的主径的周长为LOBt,lti:
LOBt,lti=regionprops(gujiaqucitizhit,lti,'perimeter')
S13.3.3.2,将周长LOBt,lti除以2就得到金枪鱼脊柱的长度l:
lt,lti=LOBt,lti/2
S14,计算倾斜角度α。
S14.1,从头部端点(Sx,Sy)开始,查找H邻域内的像素值为1的点。
S14.2,以找到的像素为1的点为中心,再次查找H邻域内的像素值为1的点。
S14.3,重复步骤S14.2,直至循环结束,所述循环结束条件是循环到第30个点,因为从头部端点开始,沿着脊柱行走30个点,基本上是一条直线,因为金枪鱼的头部那段的脊柱是直的,不会弯曲,将30个点组成的线段近似看成直线,该直线和头部脊柱那段的直线构成的角度就是鱼体的弯曲角度。
S14.4,将头部端点及查找到的像素为1的点依次存入二维数组Head。
S14.5,根据二维数组Head进行直线拟合。
采用Matlab中的polyfit函数进行直线拟合,拟合公式为:
Headp=polyfit(Head(1,:),Head(2,:),1);
式中,Headp(1)为考虑到鱼头朝向的头部的脊柱段所拟合成的直线的斜率;Head(2,:)为头部的脊柱点所构成的二维数组中的Y坐标。
S14.6,根据步骤S14.5得到倾斜角度α。
S14.6.1,得到头部的脊柱点所构成的二维数组中的Y坐标的最大值max(Head(2,:))。
S14.6.2,比较max(Head(2,:))与Sy的大小,若max(Head(2,:))等于Sy,则鱼体的倾斜角度α为:
αt,lti=arctan(Headp(1));
否则,鱼体的倾斜角度α为:
αt,lti=arctan(-Headp(1))
S15,计算弯曲角度θ。
S15.1,从交叉点TF开始,查找H邻域内的像素值为1的点。
S15.2,以像素值为1的点为中心,再次查找H邻域内的像素值为1的点。
S15.3,重复步骤S15.2,直至循环结束,所述循环结束条件是循环到第30个点,因为从交叉点开始,将尾部30个点组成的线段近似看成直线,该直线和头部脊柱那段的直线构成的角度就是鱼体的弯曲角度。
S15.4,将交叉点TF及查找到的像素值为1的点依次存入二维数组Teal。
S15.5,根据二维数组Teal进行直线拟合。
采用Matlab中的polyfit函数进行直线拟合,拟合公式为:
Tealp=polyfit(Teal(1,:),Teal(2,:),1);
其中,Tealp(1)为尾部的脊柱所拟合成的直线的斜率。
S15.6,根据步骤S15.5得到弯曲角度θ:
θt,lti=arctan((Headp(1)-Tealp(1))/(1-Headp(1)*Tealp(1)))
S16,根据步骤S9-S12或S13-S15构造候选斑块的初始模型M:
M=(Sx、Sy、l、α、θ);
S17,获取各候选斑块的轮廓上的边界点坐标。
采用matlab中的bwboundaries函数获取各个候选斑块的轮廓Bdt,lti,Bdt,lti存储的是候选斑块的边界点的坐标;
Bdt,lti=bwboundaries(SJLFt,lti,conn);
SJLFt,lti为第t个图像的第lti个候选斑块。
S18,计算初始模型M中的参考点和标记点的坐标,并计算当前候选斑块和与其对应的初始模型M之间的拟合误差指数FEI。
S18.1,计算初始模型M中的参考点坐标和标记点坐标。
S18.1.1,计算参考点vj的坐标(x’j v,y’j v):
其中,j=1,2,…,19,x0 v=0,y0 v=0;dθj为脊柱上的参考点处的局部弯曲角度,且dθj=Δθj。
S18.1.2,计算标记点ki的坐标(xi’k,yi’k)。
S18.1.2.1,右侧轮廓标记点坐标计算公式为:
其中,i=1,2,…,19;S
l为脊柱均分的长度;C
i为参考点到与它对应的右侧轮廓标记点的距离系数,
为参考点在X轴的坐标;
为参考点在Y轴的坐标。
S18.1.2.2,左侧轮廓标记点坐标计算公式为:
其中,i=21,…,39;Ci-20为参考点到与它对应的左侧轮廓标记点的距离系数。
S18.2,计算候选斑块建立的初始模型的标记点到该斑块的边界的最近距离dt,lti(ki,Bdt,lti,i)。
根据5个模型参数建立金枪鱼模型的轮廓,以轮廓上的标记点ki为中心,沿着线段kiVi的方向,向标记点ki的两侧各延伸l/64,从而构成基于标记点ki的探测线,如果该探测线与候选斑块的边界的交点为pbod,则初始模型的标记点与候选斑块的边界点匹配成功,则线段kipbod的长度就是dt,lti(ki,Bdt,lti,i)。如果ki的探测线与候选斑块的边界没有交点,则该标记点匹配失败。
S18.3,根据步骤S18.1-S18.2,计算候选斑块与初始模型的拟合误差指数FEI。
其中,lt,lti是模型的脊柱长度,m是与候选斑块边界点成功匹配的初始模型的标记点的数量;dt,lti(ki,Bdt,lti,i)是根据候选斑块建立的初始模型的标记点到该斑块的边界的最近距离。
S19,根据候选斑块的边界点和M的标记点相匹配的数量以及拟合误差指数FEI,判断候选斑块是否为一条完整的金枪鱼。
拟合误差指数FEI为0,则表示候选斑块和对应的初始模型M之间的完美契合;如果找到至少35个候选斑块的边界点与M的标记点相匹配,并且拟合误差指数FEI≤2.23,则判定候选斑块是一条完整的金枪鱼。
下面以构造金枪鱼初始模型以及后续处理对本发明的技术方案进一步解释说明
本发明选择了一个鱼体处于伸直状态的中等尺寸的成年金枪鱼,如图3所示,图中,点v0~v19是沿着脊柱的参考点。点k0~k19是外部的右侧轮廓的标记点,左侧的标记点为k20~k39(其中k20与k0是同一个标记点,表示头部顶点,该点也与脊柱上的参考点v0重合),并且k21~k39与k1~k19分别相对于脊柱上的参考点v1~v19对称。图3中的各个小正方形网格的边长为Sl。
金枪鱼的初始模型是包含金枪鱼外部轮廓上的40个标记点的集合K,分别以20个标记点代表金枪鱼鱼体轮廓的左右两侧,点v0(同时也是k0)为金枪鱼的头部顶点。设定金枪鱼的头部到尾部的脊柱的长度为l,脊柱所在的直线为X轴,k0为原点,向右为正方向;与X轴垂直的为Y轴,向下为正方向。将该长度为l的脊柱分成16个等长的线段Sl,每段Sl的长度为l/16,Sl作为一个测量单位来辅助定义脊柱上的参考点的位置。
在图3中,小的正方形网格的大小为Sl×Sl。脊柱上的参考点vi对应于轮廓上的标记点ki(i=1,2…19),Vi-20对应于ki(当i=21,21…39时)。为了定义胸鳍的轮廓,采用v5、v6、v7、v8和v9这5个参考点表示胸鳍对应的脊柱部分,胸鳍的外部的右侧轮廓上的标记点为k5、k6、k7、k8和k9这5个点。为表现足够多的细节,v5、v6、v7、v8和v9中相邻两个参考点在X轴上的距离为0.25Sl。脊柱上的参考点v5距离头部参考点v0的距离为4.7Sl,胸鳍的右侧外部轮廓上的标记点垂直投影到脊柱上的位置也一般位于从头部开始向右的4.7Sl处的X轴上,该位置可作为胸鳍外部轮廓的标记点的特征位置。总之,本发明定义了一组有序的20个脊柱上的参考点的位置。从头部的脊柱开始到尾部的脊柱结束,可以写成:vj=(v0,v1,v2,v3,...,v19)。这些点在X轴上的增长量的系数是Δxj v。
Δxj v=[0,1,1,1,1,0.7,0.25,0.25,0.25,025,1.3,1,1,1,1,1,1,1,1,1];
其中
从而计算脊柱上的参考点v
j的坐标(x
j v,y
j v)。
根据图3所示的金枪鱼初始模型中做出如下设定:(1)金枪鱼身体的厚度或宽度都与长度呈正比,因此也与Sl呈正比;(2)从金枪鱼下方的水体中拍摄获得图像中的金枪鱼的体型相对于其脊柱是对称的。脊柱上的每个参考点与相应的轮廓上的标记点对应,比如v1分别对应于k1、k21;v2分别对应于k2、k22;v3分别对应于k3、k23;依此类推。
对于金枪鱼的初始模型,计算从脊柱的参考点到与它对应的右侧外部轮廓标记点的距离,并且获得距离系数C。C中的每个系数Ci代表着d(vi,ki)和Sl之间的比例关系;d(vi,ki)为脊柱点vi到相对应的轮廓上的标记点ki的距离。C的20项参数为:
C=[0,0.7,1.15,1.35,1.55,1.65,2.0,2.5,2.8,3.15,1.7,1.55,1.35,1.1,0.9,0.7,0.55,0.45,0.5,0.75];
头部顶点是脊柱上的参考点v0(该点和标记点k0、k20是同一个点),所以d(v0,k0)=0。考虑到鱼体的对称性,同理可得到,鱼体外部的左侧轮廓的20个标记点到相对应的参考点的距离系数C',C'与C的对应位置的参数的大小相等、方向相反。所以标记点的坐标ki(xi k,yi k)可以由以下公式获得。
总之,一旦金枪鱼的脊柱上的参考点vi的位置确定,相应的标记点ki可以根据距离脊柱点左右两侧的法线方向上的距离d(vi,ki)=Ci*Sl来确定。
而图3是比较理想状态下获得的金枪鱼状态,大多数情况下金枪鱼在游动时,鱼体做了一个不均匀分布的全局弯曲。鱼体在脊柱上的全局弯曲的角度设定为θ,由脊柱上的参考点v0~v19依次相互连接组成脊柱。
其中,dθj代表脊柱上相邻的两个脊柱段(把脊柱段Vj-1Vj、Vj Vj+1作为两条线段)的夹角(设定线段V-1V0与V0V1的夹角dθ0为0,线段V18V19与V19V20的夹角dθ19为0.17θ),即不同的脊柱段对整体弯曲的增加量,也叫局部弯曲角度。
在实际研究中,当鱼体弯曲时,弯曲的程度集中在鱼体的中部到尾部,如图4所示。脊柱上的20个参考点(从头部向尾部排列)相对于头部的弯曲程度逐渐增加,脊柱上的参考点vi相对于vi-1对整体弯曲的增加量为Δθi,使用矢量Δθ表示20个局部弯曲的增加量为:Δθ=[0,0,0.04θ,0.04θ,0.03θ,0.03θ,0,0,0,0,0.03θ,0.04θ,0.05θ,0.06θ,0.07θ,0.08θ,0.09θ,0.12θ,0.15θ,0.17θ];
其中
尾部附近的参考点的弯曲度增加量最大(Δθ
19=0.17θ),而头部附近的脊柱上的参考点没有弯曲的可能性(Δθ
0=0)。脊柱上的参考点v
5、v
6、v
7、v
8和v
9相距较近,对鱼体弯曲模型的贡献较小,在描述非均匀分布的弯曲时,忽略了参考点v
6、v
7、和v
8,即将这3个参考点对脊柱弯曲的增加量设定为0。
图4显示了有17个参考点的非均匀的弯曲分布。对于这种非均匀的分布,脊柱上的参考点处的局部弯曲角度dθj可以通过如下公式得到:
dθj=Δθj;
一旦金枪鱼的全局弯曲角度θ被确定,就可以计算弯曲的脊柱上的参考点vi的位置及在脊柱段的法线方向上的标记点的位置。在弯曲的脊柱上的每个参考点的坐标vj(xj v,yj v),可以通过如下公式得到。
其中,j=1,2,…,19。x0 v=0,y0 v=0。
考虑到所有外部轮廓上的标记点的坐标为Ki(xi k,yi k),可以通过如下公式计算得到。
其中,i=1,2,…,19。
其中,i=21,…,39。
图5显示了脊柱上的参考点所对应的轮廓标记点,以及由初始模型产生的全局弯曲(全局弯曲分别为θ=15°、θ=30°和θ=45°)。
为了实现模型对尺度变化、平移和旋转不敏感,本发明的金枪鱼模型M最终由五个参数定义,M=[Sx,Sy,l,α,θ],如图6所示。其中,平移参数Sx和Sy由图像中的金枪鱼头部顶点位置确定,l是脊柱的长度(l=16Sl),l给出了尺度因子;α表示模型的刚性旋转,定义为鱼头部的脊柱段V0V1与X轴的角度,以及脊柱的全局弯曲角度θ。如果α=0,表示鱼头指向X轴的正方向,且鱼头部位的脊柱段V0V1正好与X轴平行。刚性变换矩阵可写成:
而为了获取初始模型M的5个参数,进行连通区域标记,标记图像中的每个斑块,然后对各个候选斑块分别进行处理,并提取模型参数。
首先剔除接触图像边界的斑块,然后根据连通区域标记的信息,删除面积较小的斑块,然后针对图像Binrfct中的剩余的每个候选斑块进行分析,提取各个候选斑块的参数。
采用matlab中的函数imclearborder进行边界对象抑制,删除包含图像边界的连通区域。采用的具体参数为;
Bcbt=imclearborder(Binrfct,conn);
其中,conn为8。该函数删除了二值图像Binrfct中包含边界的斑块,并保存为Bcbt。
二值化图像分析最重要的方法就是连通区域标记,它通过对二值化图像中各个斑块的标记让每个单独的连通区域形成一个被标识的斑块,可进一步地可以获取这些斑块的面积、轮廓、外接矩形、质心和不变矩等几何参数。
本发明采用Matlab中连通区域标记函数bwlabel,该函数的算法是一次遍历图像,并记下每一行(或列)中连续的团和标记的等价对,然后通过等价对对原来的图像进行重新标记。这个算法是目前效率较高的一个,算法中用到了稀疏矩阵与Dulmage-Mendelsohn分解算法用来消除等价对。
[JLt,NUMt]=bwlabel(Bcbt,8);
其中NUMt表示图像Bcbt中连通区域的数量,即斑块的数量。JLt表示和Bcbt大小相同的矩阵,JLt矩阵包含了标记了Bcbt中每个连通区域的类别标签,这些标签的值为1,2,…,NUMt。8表示是按8邻域寻找连通区域。
采用Matlab中regionprops函数,函数包含的'Area'属性表示图像各个连通区域的分别包含的像素总数。
statust=regionprops(JLt,'Area');
设定scxy的取值范围为1~NUMt,则statust(scxy,1)表示第scxy个连通区域的面积。依次将各个连通区域的面积和设定值2200相比较,如果第scxy个连通区域的面积statust(scxy,1)小于2200,则将与矩阵JLt中的值为scxy的元素的位置相同的Bcbt处的像素值置0,从而去除了图像Bcbt中的面积小于2200个像素的斑块。
再次采用Matlab中连通区域标记函数bwlabel,标记图像Bcbt。
[SJLt,SNUMt]=bwlabel(Bcbt,8)
SNUMt表示图像Bcbt中连通区域的数量,即候选斑块的数量。SJLt表示和Bcbt大小相同的矩阵,SJLt矩阵包含了标记了Bcbt中每个连通区域的类别标签,这些标签的值为1,2,…,SNUMt。8表示是按8邻域寻找连通区域。
由于金枪鱼在水中游动,所拍摄的图像中的候选斑块如果是单条完整的金枪鱼,其尾鳍的形状变化较多,可能出现尾鳍居中竖直呈直线,如图7(a)所示;尾鳍也可能呈对称分叉状,如图7(b)所示;尾鳍也可能呈新月形,如图7(c)所示。对初始模型参数进行提取的流程如图8所示。
具体是设定SJLFt,1=SJLt,将SJLFt,1中值为2~SNUMt的元素置0,则提取出了图像Bcbt的第1个连通区域。
设定SJLFt,2=SJLt,将SJLFt,2中的值为1、3~SNUMt的元素置0,则提取出了图像Bcbt的第2个连通区域。
设定lti的值为1~SNUMt,则设定SJLFt,lti=SJLt,将SJLFt,lti中的值为0的元素保留,值为lti的元素置1,其它值的元素置0,则分别提取出了图像Bcbt的第lti个连通区域。各个连通区域作为候选斑块,后续进行金枪鱼的参数提取,以及好鱼、坏鱼的判定。
采用Matlab中的bwmorph函数对各个候选斑块进行形态学操作。其中的'skel'属性是进行骨架提取,同时保持骨架不发生断裂;应用形态学操作xn次,xn可以是Inf,这种情况下该操作被重复执行直到各连通区域的骨架不再发生变化为止。
gujiat,lti=bwmorph(SJLFt,lti,'skel',xn);
图7中的尾鳍存在的变化的三种情况将分别得到对应的图像,如图9(a)、9(b)、9(c)所示。
采用Matlab中的bwmorph函数中包含'spur'属性,可以去除小的分支,即可形象的比喻为去除“毛刺”。
gujiaqucit,lti=bwmorph(gujiat,lti,'spur',4);
其中,4表示应用形态学操作4次,可有效的去除毛刺,结果如图10所示。
图10去除骨架的毛刺
采用Matlab中的bwmorph函数中包含'endpoints'属性,用于查找骨架的端点。
duandiant,lti=bwmorph(gujiaqucit,lti,'endpoints');
端点包含金枪鱼的头部端点、尾部端点以及胸鳍两侧的端点,根据图10(a)、10(b)、10(c)分别得到4、5、5个端点。得到的端点如图11(a)、11(b)、11(c)所示。如果候选斑块的端点数量小于4,或者大于5;则将该候选斑块排除,判定为坏鱼。
对于候选斑块检测到4个端点时的模型参数提取,按照从上到下,从左到右的顺序,提取endpt1、endpt2、endpt3和endpt4这四个端点的坐标依次为(x1,y1)、(x2,y2)、(x3,y3)、(x4,y4)。根据如图12所示的金枪鱼的形态特征进行分析,可以得出在任何一个金枪鱼的图像中,头部端点到尾部端点的距离(JAJD)最大;头部端点到胸鳍两侧的端点的距离小于尾部端点到胸鳍两侧的端点的距离(JAJB<JDJB或者JAJC<JDJC)。
则根据四个端点的坐标,分别计算每两个端点之间的距离d12(endpt1与endpt2的距离)、d13、d14、d23、d24、d34。如果其中的最大值为d14,则endpt1和endpt4分别为头部或者尾部端点。然后选定一个胸鳍端点endpt2,如果d12>d24,则endpt1为尾部端点,endpt4为头部端点;如果d12<d24,则endpt4为尾部端点,endpt1为头部端点。头部端点的坐标为St,lti,x=x1,St,lti,y=y1。
如果d12、d13、d14、d23、d24、d34的距离最大值为d12(或者d13、或者d23、或者d24、或者d34),同理,采用上述方法判别头部端点和尾部端点。
剔除金枪鱼骨架中表示胸鳍的两个支径,剩余的部分就是表示金枪鱼脊柱的主径。根据之前提取的金枪鱼的表示胸鳍的端点endpt2和endpt3。剔除骨架中表示胸鳍的支径的流程图,如图13所示。
剔除分别以胸鳍的两个端点为起点的两条表示胸鳍的支径后,并保存为gujiaqucitizhit,lti。此时所表示的主径就是金枪鱼的身体长度l,如图14所示。
采用Matlab中regionprops函数,函数包含的'perimeter'属性表示,连通区域的周长。则包含金枪鱼的骨架的主径的周长为LOBt,lti。
LOBt,lti=regionprops(gujiaqucitizhit,lti,'perimeter');
将周长除以2得到金枪鱼的脊柱长度lt,lti=LOBt,lti/2。
从头部端点(Sx,Sy)开始,查找其8邻域内的像素值为1的点Pn,1;然后以点Pn,1为中心,查找其8邻域内的像素值为1的点Pne,2;以此查找方式,直到点Pne,30;将头部端点及后续查找到的Pne,1~Pne,30依次存入二维数组Head。采用Matlab中的polyfit函数进行直线拟合。
Headp=polyfit(Head(1,:),Head(2,:),1);
Headp(1)即为头部的脊柱段所拟合成的直线的斜率,考虑到鱼头朝向的方向。如果max(Head(2,:))等于Sy,则鱼体的倾斜角度αt,lti为arctan(Headp(1));否则鱼体的倾斜角度αt,lti为arctan(-Headp(1))。其中max(Head(2,:))表示头部的脊柱点所构成的二维数组中的Y坐标的最大值。
从尾部端点开始,查找其8邻域内的像素值为1的点Pw,1;然后以点Pw,1为中心,查找其8邻域内的像素值为1的点Pw,2;以此查找方式,直到点Pw,30;将尾部端点及后续查找到的Pw,1~Pw,30依次存入二维数组Teal。采用Matlab中的polyfit函数进行直线拟合。
Tealp=polyfit(Teal(1,:),Teal(2,:),1);
Tealp(1)即为尾部的脊柱所拟合成的直线的斜率。则鱼体的弯曲角度θt,lti为:
arctan((Headp(1)-Tealp(1))/(1-Headp(1)*Tealp(1)));
当候选斑块检测到5个端点时的模型参数提取,按照从上到下,从左到右的顺序,提取endpt1、endpt2、endpt3、endpt4和endpt5这5个端点的坐标依次为(x1,y1)、(x2,y2)、(x3,y3)、(x4,y4)、(x5,y5)。根据此时金枪鱼的形态特征分析,如图15所示,可以得出在出现5个端点时,尾鳍的两个端点之间的距离JCJD最小。分别计算这5个端点((x1,y1)、(x2,y2)、(x3,y3)、(x4,y4)、(x5,y5))中所有的2个端点组成线段的距离,找出其中两个端点所构成线段的最小距离,并将这两个端点分别命名为JC、JD。然后选取JC为出发点,分别计算JC与剩余3个端点的距离,查找距离最大的值时所对应的端点,并将该端点命名为JA。此时JA就是模型的头部端点,即头部端点的x坐标St,lti,x等于JA的x坐标,头部端点的y坐标St,lti,y等于JA的y坐标。
最后剩余的两个端点分别命名为JB、JE。由此得到了头部端点、尾鳍端点、胸鳍端点的坐标。
采用Matlab中的bwmorph函数中包含'branchpoints'属性,用于查找骨架的交叉点。
jiaochadiant,lti=bwmorph(gujiaqucit,lti,'branchpoints');
此时jiaochadiant,lti中包含胸鳍和脊柱的交叉点PF、尾鳍和脊柱的交叉点TF这两个交叉点的坐标。分别计算jiaochadiant,lti中的两个交叉点到JA的距离,将距离值较小的交叉点命名为PF,将距离值较大的交叉点命名为TF,从头部顶点JA沿着脊柱行走到TF的距离就是金枪鱼的脊柱长度lt,lti。
为了计算脊柱长度,需要剔除金枪鱼骨架中表示胸鳍的两个支径以及表示尾鳍的两个支径,剩余的部分就是表示金枪鱼脊柱的主径。根据之前提取的表示胸鳍和脊柱的交叉点PF、尾鳍和脊柱的交叉点TF。采用图13中的方法分别剔除骨架中表示胸鳍的支径、尾鳍的支径(当要剔除尾鳍的支径时,分别以表示尾鳍的端点为中心点Pcenter,后续的处理步骤与图13中的相同)。
剔除以胸鳍的两个端点为起点的两条表示胸鳍的支径、以尾鳍的两个端点为起点的两条表示尾鳍的支径,并保存为gujiaqucitizhit,lti。此时所表示的主径就是金枪鱼的身体长度。
采用Matlab中regionprops函数,函数包含的'perimeter'属性表示,连通区域的周长。则包含金枪鱼的骨架的主径的周长为LOBt,lti。
LOBt,lti=regionprops(gujiaqucitizhit,lti,'perimeter');
将周长除以2得到金枪鱼的骨架的主径,金枪鱼的脊柱长度lt,lti=LOBt,lti/2。
倾斜角度α的计算方法与候选斑块检测到4个端点时的倾斜角度的获取方法相同。
当计算弯曲角度θ时,从交叉点TF开始,后续计算方法与候选斑块检测到4个端点时计算弯曲角度的方法相同。
计算拟合误差
采用matlab中的bwboundaries函数获取各个候选斑块的轮廓Bdt,lti,Bdt,lti存储的是候选斑块的边界点的坐标。
Bdt,lti=bwboundaries(SJLFt,lti,8);
针对第t个图像的第lti个连通区域(即候选斑块)SJLFt,lti,获得初始模型Mt,lti(包括St,lti,x、St,lti,y、lt,lti、αt,lti、θt,lti),然后根据之前的公式计算参考点、标记点的坐标。
拟合的目的是,比较候选斑块SJLFt,lti与初始模型参数Mt,lti的误差。初始模型与对应的候选斑块之间的差异被定义为基于二次距离dt,lti(ki,Bdt,lti,i)的拟合误差指数,dt,lti(ki,Bdt,lti,i)表示计算得到的标记点Ki和对应的候选斑块边界点Bdt,lti,i的距离,它可以写成:
其中,34<m≤39,lt,lti是模型的脊柱长度,用于确保尺度不变性;dt,lti(ki,Bdt,lti,i)是根据候选斑块建立的初始模型的标记点到该斑块的边界的最近距离(根据5个模型参数建立金枪鱼模型的轮廓,以轮廓上的标记点ki为中心,沿着线段kiVi的方向,向ki的两侧各延伸l/64,从而构成基于ki的探测线,如果该探测线与候选斑块的边界的交点为pbod,则初始模型的标记点与候选斑块的边界点匹配成功,则线段kipbod的长度就是dt,lti(ki,Bdt,lti,i));m是与候选斑块边界点成功匹配的初始模型的标记点的数量。图16(a)显示了根据探测线查找与初始模型的标记点所对应的候选模块边界点的过程。图16(b)描绘图16(a)中的每个实现匹配的dt,lti(ki,Bdt,lti,i)。当拟合误差指数FEI为0,则表示候选斑块SJLFt,lti和模型Mt,lti,之间的完美契合。如果在斑块中找到至少35个匹配的标记点(m>34),并且FEI≤2.23,判定候选斑块是一条完整的金枪鱼。
通过实验进一步评估所建立初始模型的准确性。使用两个不同的水下摄像机获取视频图像,图像包含复杂的场景(持续游动的金枪鱼、低对比度、水体混浊、粘连重叠的鱼群、变化的照明条件)。判断检测到的候选斑块SJLFt,lti是否为一条完整的金枪鱼,对斑块的识别标记过程如图17所示。
由图17可知,本发明对接触图像边界的斑块、面积小于2200像素的斑块、两条鱼体粘连的斑块及表示单条好鱼的斑块都做出了精准的识别和标记。虽然整个视频图像的照明不均匀,但在图像中的15×15像素的小范围内的照明相对较为均匀,在该范围内应用局部阈值方法,分割效果良好。测试了最小斑块的阈值为2200。进行1000个斑块的试验,实验结果表明,最好的分类结果是FEI=2.23,最小斑块面积阈值为2200像素,单条完整金枪鱼检测的成功率为92%。
上面所述仅为本发明的较佳实施例而已,并不用以限制本发明,凡在本发明的精神和原则之内,所作的任何修改、等同替换、改进等,均应包含在本发明的保护范围之内。