表示和描述
Posted zizi7
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了表示和描述相关的知识,希望对你有一定的参考价值。
接上篇 表示和描述(1)
边界描述
主要讨论边界的形状数描述、傅里叶描述和其他简单的描述。
1)基础描述
边界长度:边界的像素数粗略近似
边界直径:相隔最远的两个点的距离(链码一节介绍的长短轴)
边界偏心率:长轴/短轴
其他规范化近似:外接圆、外接矩形、外接凸包
2)形状数描述
参考表示和描述(1)的Freeman编码,图1-2形状编号的长度即为形状数的阶。
这个概念的意义在于,你可以指定一个边界的阶(以4-方向为例,对于闭合边界,其阶为大于等于4的偶数),然后对边界做重采样。
如图1-2中指定形状数阶数为18,首先获得其基本矩形(左2),然后计算其最接近18的划分(6*3,左3)。
在轮廓匹配中,可以用形状数作为参考:以4-方向为例,依次取阶数K=4,6,8...2n(显然随着K的增大,边界描述越精确),对待匹配的两组边界生成形状数,比较两组形状数,取d为使得两者相同的最大阶。显然对于相同的两条边界,d=无穷大。
3)傅里叶描述
使用一个复数来描述一个点:s(k) = x(k) + jy(k),然后对其做离散傅里叶变换:
这里介绍频域的4种边界操作(图2-1):一种是通过忽略部分高频傅里叶系数获得边界的近似描述(低频决定边界形状,高频决定边界细节);另三种是旋转、平移、缩放。
a. 边界近似
取前P个傅里叶系数做逆变换:。方便起见,直接将后K-P个系数赋0做逆变换就可以了。
b. 边界旋转
需要注意的是这里的旋转是以序列中(0,0)为原点的,将序列减去质心就可以实现以质心为原点旋转了。
c. 边界平移
,其中,乘以冲击序列的傅里叶变换
d. 边界缩放
,其中a为缩放系数
图2-1. 边界傅里叶描述
如图2-1所示,a为原始图像,b~e为使用Moore边界追踪算法后在频域做平移、旋转、缩放、近似。其中旋转部分做了中心平移,近似部分取前2/3的傅里叶系数做逆变换。
此外,边界还可以用统计矩来描述,但一般对区域的不变矩描述更广泛。
区域描述
主要讨论区域的纹理描述、不变矩描述和其他简单描述
1)基础描述
区域面积、周长都是用相应像素数来粗略估计
区域致密性:(周长)^2 / 面积。显然圆形具有最小的致密性。
区域圆度率:区域面积 / 具有相同周长的圆的面积。
2)纹理描述
纹理描述主要有三种方法:统计方法、结构方法、频谱方法。
统计方法考察纹理的平滑、粗糙、粒状等特征;结构方法考察纹理的排列描述;频谱方法考察纹理的周期性。
以下主要讨论统计方法的几种指标
a. 统计矩
对一个区域,统计其归一直方图,计算其均值的z的第n阶矩为,其中m是平均灰度。
n=2:二阶矩(方差),描述区域的灰度对比变化。由其构成的归一化R度量对粗糙的区域有较大响应
n=3、4:三阶矩度量直方图倾斜性(负数表示总体小于均值),四阶矩度量直方图平坦度。
此外还有个重要的度量:直方图熵,描述区域的信息量。
b. 灰度共生矩阵(GLCM)
GLCM不仅考察灰度分布,还考虑了像素的相对位置。
令Q为两个像素相对位置的一个定义(比如当前像素的右邻像素),G为针对区域f由Q生成的共生矩阵(对于8bit图像,大小为256*256)。按当前Q定义,g_ij表示区域f中灰度值为i且其右邻像素灰度值为j的像素对数目(图3-1)。
图3-1. 灰度共生矩阵(《数字图像处理》)
令,由GLCM可得到以下统计量
对比度:,纹理越深,该值越大
相关性:,其中,。邻域变化越小,相关性值越大。
能量:,能量越大表示当前纹理越规则
熵:,熵越大表示当前纹理越复杂
3)不变矩描述
令图像f(x,y)尺寸M*N,其二维(p+q)阶为,相应的(p+q)阶中心矩为,其中。
由以上定义获得其归一化中心矩:,其中。
根据归一化中心矩可获得7个不变矩(hu不变矩),其对同一区域的平移、缩放、旋转、镜像能保持一致描述
OpenCV有hu不变矩的实现:
// 处理图像
int i, j;
Mat src = imread("../DIP_CODE+IMAGE/IMAGE/dipum_images_ch11/Fig1123(a)(Original_Padded_to_568_by_568).tif",0);
Mat shift_(src.size(), CV_8UC1, Scalar::all(0)); // 平移
for (i = 0; i < src.rows-50; i++)
{
uchar* ptrSrc = src.ptr<uchar>(i);
uchar* ptrShift = shift_.ptr<uchar>(i + 50);
for (j = 0; j < src.cols-50; j++)
{
uchar value = ptrSrc[j];
if (value > 0)
ptrShift[j+50] = value;
}
}
Mat resize_(src.size(), CV_8UC1, Scalar::all(0)); // 缩放
Mat resize_tmp;
resize(src, resize_tmp, Size(src.cols/2, src.rows/2));
Mat roi_(resize_, Rect(src.cols / 4, src.rows / 4, src.cols / 2, src.rows / 2));
resize_tmp.copyTo(roi_);
Mat flip_; // 镜像
flip(src, flip_, 1);
Mat rotate_; // 旋转
Point2f center_(src.cols/2, src.rows/2);
Mat r = getRotationMatrix2D(center_, 45, 1);
warpAffine(src, rotate_, r, src.size());
namedWindow("src");
namedWindow("shift");
namedWindow("resize");
namedWindow("flip");
namedWindow("rotate");
imshow("src", src);
imshow("shift", shift_);
imshow("resize", resize_);
imshow("flip", flip_);
imshow("rotate", rotate_);
// 统计不变矩
Moments mom = moments(src);
double hu[7];
HuMoments(mom, hu);
for (i = 0; i < 7; i++)
hu[i] = log(abs(hu[i])) * (-1*hu[i]/abs(hu[i]));
cout << "************** src *****************" << endl;
for (i = 0; i < 7; i++)
cout << "hu[" << i << "]=" << hu[i] << "; ";
cout << endl;
mom = moments(shift_);
HuMoments(mom, hu);
for (i = 0; i < 7; i++)
hu[i] = log(abs(hu[i])) * (-1*hu[i] / abs(hu[i]));
cout << "************** shift *****************" << endl;
for (i = 0; i < 7; i++)
cout << "hu[" << i << "]=" << hu[i] << "; ";
cout << endl;
mom = moments(resize_);
HuMoments(mom, hu);
for (i = 0; i < 7; i++)
hu[i] = log(abs(hu[i])) * (-1*hu[i] / abs(hu[i]));
cout << "************** resize *****************" << endl;
for (i = 0; i < 7; i++)
cout << "hu[" << i << "]=" << hu[i] << "; ";
cout << endl;
mom = moments(flip_);
HuMoments(mom, hu);
for (i = 0; i < 7; i++)
hu[i] = log(abs(hu[i])) * (-1*hu[i] / abs(hu[i]));
cout << "************** flip *****************" << endl;
for (i = 0; i < 7; i++)
cout << "hu[" << i << "]=" << hu[i] << "; ";
cout << endl;
mom = moments(rotate_);
HuMoments(mom, hu);
for (i = 0; i < 7; i++)
hu[i] = log(abs(hu[i])) * (-1*hu[i] / abs(hu[i]));
cout << "************** rotate *****************" << endl;
for (i = 0; i < 7; i++)
cout << "hu[" << i << "]=" << hu[i] << "; ";
cout << endl;
waitKey(0);
接下篇 表示和描述(3)
以上是关于表示和描述的主要内容,如果未能解决你的问题,请参考以下文章
2021-12-24:划分字母区间。 字符串 S 由小写字母组成。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。返回一个表示每个字符串片段的长度的列表。 力扣763。某大厂面试