2019-01-21 22:21:54 qq_42887760 阅读数 850

矩的概念介绍

可以参考:https://blog.csdn.net/keith_bb/article/details/70197104

  • 几何矩( 其中P(i,j)为图像在坐标点(i,j)处的灰度值。)
    在这里插入图片描述
  • 中心距在这里插入图片描述
  • 中心归一化距
    在这里插入图片描述
    其中:图像中心Center(x0, y0)。 此非图像坐标的中心点,而是图像 质 的中心,质点
    在这里插入图片描述

API介绍与使用 – cv::moments 计算生成数据

在这里插入图片描述

API介绍与使用-计算矩cv::moments

opencv中提供了moments()来计算图像中的中心矩(最高到三阶),HuMoments()用于由中心矩计算Hu矩.同时配合函数contourArea函数计算轮廓面积和arcLength来计算轮廓或曲线长度

  • moments( // 计算矩,返回 0阶到3阶所有的几何矩,2阶到3阶所有的中心矩,2阶到3阶所有的中心归一矩
    InputArray array,//输入数据,findContours 找到的轮廓数据
    bool binaryImage=false // 是否为二值图像
    )

    1. array:输入数组,可以是光栅图像(单通道,8-bit或浮点型二维数组),或者是一个二维数组(1 X N或N X 1),二维数组类型为Point或Point2f
    2. binaryImage:默认值是false,如果为true,则所有非零的像素都会按值1对待,也就是说相当于对图像进行了二值化处理,阈值为1,此参数仅对图像有效。
  • contourArea(
    InputArray contour,//输入轮廓数据
    bool oriented// 默认false、返回绝对值)

    1. contour:是一个向量,二维点,可以是vector或Mat类型
    2. oriented:有默认值false,面向区域标识符,如果为true,该函数返回一个带符号的面积,其正负取决于轮廓的方向(顺时针还是逆时针)。根据这个特性可以根据面积的符号来确定轮廓的位置。如果是默认值false,则面积以绝对值的形式返回.
    3. 该函数使用Green formula计算轮廓面积,返回面积和非零像素数量如果使用drawContours或fillPoly绘制轮廓,可能导致不同。
  • arcLength( //用于计算封闭轮廓的周长或曲线的长度
    InputArray curve,//输入曲线数据
    bool closed// 是否是封闭曲线)

    1. curve:输入二维点集,可以是vector或Mat类型
    2. closed:曲线是否封闭的标志位,true则封闭否则不封闭

演示代码-步骤

在这里插入图片描述

  1. 提取图像边缘
  2. 发现轮廓
    在这里插入图片描述
  3. 计算每个轮廓对象的矩
    在这里插入图片描述
  4. 计算每个对象的中心、弧长、面积
    在这里插入图片描述

程序代码

#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;

//定义全局变量
Mat src; Mat src_gray;
int thresh = 100;
int max_thresh = 255;
RNG rng(12345);
 //声明回调函数
void thresh_callback(int, void* );
 
int main( int argc, char** argv )
{
	// 读入原图像, 返回3通道图像数据
	src = imread("E:/Experiment/OpenCV/Pictures/CircleTest2.jpg");
	// 创建新窗口
	char* source_window = "Source";
	namedWindow( source_window, CV_WINDOW_AUTOSIZE );
	imshow( source_window, src );

	// 把原图像转化成灰度图像并进行平滑
	cvtColor( src, src_gray, CV_BGR2GRAY );
	//blur( src_gray, src_gray, Size(3,3) );
	GaussianBlur(src_gray, src_gray, Size(3, 3), 0, 0);//这里用高斯模糊去噪,相比于均值,轮廓发现的准确
	imshow("灰度图", src_gray);

 
	createTrackbar( " Canny thresh:", "Source", &thresh, max_thresh, thresh_callback );
	thresh_callback( thresh, 0 );
 
	waitKey(0);
	return(0);
}
 
void thresh_callback(int, void* )
{
	Mat canny_output;
	vector<vector<Point> > contours;
	vector<Vec4i> hierarchy;
 
	// 使用Canndy检测边缘
	Canny( src_gray, canny_output, thresh, thresh*2, 3 );//提取边缘
	// 找到轮廓
	findContours( canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );//发现轮廓
 
	// 计算图像矩
	vector<Moments> mu(contours.size() );//存放各阶各种矩
	for( int i = 0; i < contours.size(); i++ ){
		//计算矩,返回 0阶到3阶所有的几何矩,2阶到3阶所有的中心矩,2阶到3阶所有的中心归一矩
		mu[i] = moments( contours[i], false ); 
	}
 
	//  计算中心矩,即图像的质心:
	vector<Point2f> mc( contours.size() );//各阶各种矩的图像中心,质点
	for( int i = 0; i < contours.size(); i++ ){
		mc[i] = Point2f( mu[i].m10/mu[i].m00 , mu[i].m01/mu[i].m00 ); 
	}
 
	// 绘制轮廓
	Mat drawing = Mat::zeros( canny_output.size(), CV_8UC3 );
	for( int i = 0; i< contours.size(); i++ ){
		Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
		drawContours( drawing, contours, i, color, 2, 8, hierarchy, 0, Point() );//绘制轮廓
		circle( drawing, mc[i], 4, color, -1, 8, 0 );//绘制质点
	}
 
	// 显示到窗口中
	namedWindow( "Contours", CV_WINDOW_AUTOSIZE );
	imshow( "Contours", drawing );
 
	// 通过m00计算轮廓面积并且和OpenCV函数比较
	printf("\t Info: Area and Contour Length \n");
	for( int i = 0; i< contours.size(); i++ ){
		printf(" * Contour[%d] - Area (M_00) = %.2f - Area OpenCV: %.2f - Length: %.2f \n", i, mu[i].m00, contourArea(contours[i]), arcLength( contours[i], true ) );
		Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
		drawContours( drawing, contours, i, color, 2, 8, hierarchy, 0, Point() );
		circle( drawing, mc[i], 4, color, -1, 8, 0 );
	}
}

运行截图

在这里插入图片描述
在这里插入图片描述

参考博客

  1. https://blog.csdn.net/keith_bb/article/details/70197104
  2. https://blog.csdn.net/huanghuangjin/article/details/81189586
  3. https://blog.csdn.net/LYKymy/article/details/83210439
2016-08-01 12:52:15 u013496193 阅读数 374

距离度量

对于坐标分别为(x,y),(s,t)和(v,w)的像素p,q和z,如果
(1)D(p,q)>=0;
(2)D(p,q)=D(q,p)
(3)D(p,z)<=D(p,q)+D(q,z);
那么D是距离函数或者度量。
三种距离表示方法
1.欧式距离
这里写图片描述
距(x,y)距离小于或者等于r的像素为中心为(x,y)且半径为r的圆平面
2.城市街区距离
这里写图片描述
距(x,y)的距离小于或者等于某个值r的像素形成一个中心的在(x,y)的菱形。
3.棋盘距离
这里写图片描述
距(x,y)的棋盘距离小于或者等于某个值r的像素形成中心在(x,y)的方形。
注意如果考虑Dm距离用点间的最短通路定义。而上述D4和D8与通路无关,通路两个像素点必须为m邻接。
我所理解的Dm距离就是最短通路的长度,重点是我们两点间的最短通路是哪条,从p到q横走或者竖走一定是可以的,只有从45度左上或者右上需要考虑是否通路的序列间是m邻接,若不是m邻接则必须横走或者竖走

2019-04-14 09:09:41 mary_0830 阅读数 190

(一)在频域中直接生成滤波器

(1)建立网格数组以实现频域滤波器

在这篇博客中,主要写的是循环对称滤波器,它们是由距滤波器中心点的距离的不同函数规定的。为实现这些滤波器而开发的M-函数是基础,并且可以很容易地推广到相同结构的其他函数中。

在上一篇博客中运用到了dftuv的M-函数,这用于生成网格数组来实现频域滤波器。

function [U,V] = dftuv(M,N)   % dftuv的M-函数
u = single(0:(M-1));  
v = single(0:(N-1));    %建立变量范围
idx = find(u >M/2);   
u(idx) = u(idx) - M;
idy = find(v >N/2);
v(idy) = v(idy) - N;  %计算在meshgrid中使用的索引
[V,U] = meshgrid(v,u);   %计算在meshgrid中行列

调用dftuv函数:

[U,V]=dftuv(8,5);
DSQ= U.^2+V.^2
fftshift(DSQ)    %使用函数 fftshift 得到频域矩形中心的距离

实验结果:

在这里插入图片描述

fftshift(DSQ) 结果,如图:
在这里插入图片描述

(2)频域低通(平滑)滤波器

实验代码:

f = imread('C:\Users\Public\Pictures\Sample Pictures\Fig0313(a).tif ');
[f,revertclass] = tofloat(f);
PQ = paddedsize(size(f));
[U,V] = dftuv(PQ(1),PQ(2));
D = hypot(U,V);
D0 = 0.05*PQ(2);
F = fft2(f,PQ(1),PQ(2)); 
H = exp(-(D.^2)/(2*(D0^2)));
g = dftfilt(f,H);
g = revertclass(g);
subplot(221),imshow(f), title('原图像');
subplot(222),imshow(fftshift(H)), title('以图像显示的高斯低通滤波器');
subplot(223),imshow(log(1+abs(fftshift(F))),[]), title('滤波后的图像谱');
subplot(224),imshow(g), title('滤波后的图像谱');

实验结果:
在这里插入图片描述

在这里插入图片描述

实验结论:
通过上述两幅图片的比较,低通(平滑)滤波器的作用是平滑图像,但是会模糊图像。以上的实验代码可以说明此代码可以用于灰度图像的平滑图像。

(3)线框及表面绘制

说明:下面将介绍3D线框及表面的绘制,基本语法如下:

mesh(H)  
mesh(H(1:k:end,1:k:end))       %用于绘制第k个点
colormap([0 0 0])            %用于设置线框颜色([0 0 0]黑色,默认值是彩色线框)
gird off                    %关掉网格命令
axis off            %关掉轴的命令
view(az,el)     %设置观察者位置

实验代码:

H = fftshift(lpfilter('gaussian',500,500,50));
mesh(double(H(1:10:500,1:10:500)))

实验结果:
在这里插入图片描述

实验代码:

H = fftshift(lpfilter('gaussian',500,500,50));
mesh(double(H(1:10:500,1:10:500)))    %建立线框图
axis tight           % 产生线框图
colormap([0 0 0])     %将线框颜色变成黑色

实验结果:
在这里插入图片描述

实验代码:

colormap([0 1 0])     %将线框颜色变成绿色,三个数字分别表示红绿蓝,且colormap的值必须位于【0,1】之间。

在这里插入图片描述

实验代码:

colormap([0.8 1 0])     %将线框颜色变成淡黄色

在这里插入图片描述

实验代码:

H = fftshift(lpfilter('gaussian',500,500,50));
mesh(double(H(1:10:500,1:10:500)))
axis tight
colormap([0 0 0])
axis off         %消除坐标轴
grid off        %消除栅格

在这里插入图片描述

实验代码:

H = fftshift(lpfilter('gaussian',500,500,50));
mesh(double(H(1:10:500,1:10:500)))
axis tight           %设置坐标轴显示范围为紧凑型 
colormap([0 0 0])
axis off 
grid off
view(-25,0)        %将观察者的视角设置为方位角为-25且仰角设置为0

在这里插入图片描述

实验代码:

view(-10,-10)      %将观察者的视角设置为方位角为-10且仰角设置为-10

在这里插入图片描述
有时候用surf函数可以绘制表面图:

surf(H)

实验代码:

H = fftshift(lpfilter('gaussian',500,500,50));
surf(double(H(1:10:500,1:10:500)));
axis tight
colormap(gray)           %将颜色转为灰度
shading interp           %平滑小面描影和消除栅网线
[Y,X] = meshgrid(-2:0.1:2,-2:0.1:2);   %用于产生坐标值
Z = X.*exp(-X.^2 - Y.^2);

实验结果:
在这里插入图片描述

实验结论:
函数mesh是用来显示线框图,而surf是用于显示表面图。

(二)高通(锐化)频域滤波器

高通滤波器函数hpfilter:

function H = hpfilter(type, M, N, D0, n)
if nargin == 4
    n = 1; %默认值为1
end
Hlp = lpfilter(type,M,N,D0,n);
H = 1-Hlp;

实验代码:

H1 = fftshift(hpfilter('ideal',500,500,50));
H2 = fftshift(hpfilter('gaussian',500,500,50));
H3 = fftshift(hpfilter('btw',500,500,50));
mesh(double(H1(1:10:500,1:10:500)));
mesh(double(H2(1:10:500,1:10:500)));
mesh(double(H3(1:10:500,1:10:500)));
axis tight
axis off
subplot(131),imshow(H1), title('理想高通滤波器');
subplot(132),imshow(H2), title('高斯高通滤波器');
subplot(133),imshow(H3), title('巴特沃斯高通滤波器');

实验结果:
在这里插入图片描述

实验代码:

f = imread('C:\Users\Public\Pictures\Sample Pictures\flower.jpg ');
PQ = paddedsize(size(f));
D0 = 0.05*PQ(1);
H = hpfilter('ideal',PQ(1),PQ(2),D0);
g = dftfilt(f,H);
subplot(121),imshow(f),title('原始图像');
subplot(122),imshow(g,[]),title('理想高通滤波器后的图像');

实验结果:
(图一)
在这里插入图片描述

(图二)
在这里插入图片描述

实验代码:

f = imread('C:\Users\Public\Pictures\Sample Pictures\flower.jpg ');
PQ = paddedsize(size(f));
D0 = 0.05*PQ(1);
H = hpfilter('btw',PQ(1),PQ(2),D0);
g = dftfilt(f,H);
subplot(121),imshow(f),title('原始图像');
subplot(122),imshow(g,[]),title('巴特沃斯高通滤波器后的图像');

实验结果:
(图三)
在这里插入图片描述

>> f = imread('C:\Users\Public\Pictures\Sample Pictures\timg.jpg ');
>> PQ = paddedsize(size(f));
D0 = 0.05*PQ(1);
H = hpfilter('ideal',PQ(1),PQ(2),D0);
g = dftfilt(f,H);
subplot(121),imshow(f),title('原始图像');
subplot(122),imshow(g,[]),title('理想高通滤波器后的图像');

(图四)
在这里插入图片描述

实验结论: 对比图一和图二,不同图像的高斯高通滤波器滤除的边缘有差异,高斯高通滤波器很明显的可以显示出图像的边缘。对比图一和图三,巴特沃斯比高斯滤出的边缘细节更多。对比图二和图四,使用理想高通滤波器的图像产生了振铃效应。理想滤波器的特性通常用来解释振铃现象。 图像处理中,对一幅图像进行滤波处理,若选用的频域滤波器具有陡峭的变化,则会使滤波图像产生“振铃”。振铃就像是一块石头投进水中,产生一波一波的水纹。
这三种滤波方式用于不同的情况,若需要更多细节,可以用理想或者巴特沃斯,但理想滤波器会产生振铃效应;若只需要边界,可以用巴特沃斯或者高斯。

(三)选择性滤波

(1)带通和带阻滤波器

function H = bandfilter(type,band,M,N,D0,W,n)
if nargin < 7
    n = 1;  %默认值
end
switch lower(type)
    case 'ideal'
        H = idealReject(D,D0,W);
    case 'btw'
        H = btwReject(D,D0,W,n);
    case 'gaussian'
        H = gaussianReject(D,D0,W);
    otherwise
        error('Unknown filter type.')
end

if strcmp(band,'pass')
    H = 1 - h;
end

%------------------------------------------------------------------%
function H = idealReject(D,D0,W)
RI = D <= D0 - (W/2);
RO = D >= D0 + (W/2);
H = tofloat(RO|RI);
%------------------------------------------------------------------%
function H = btwReject(D,D0,W,n)
H = 1./(1 + ((D*W)./(D.^2 - D0^2)).^2*n));
%------------------------------------------------------------------%
function H = gaussianReject(D,D0,W)
H = 1 - exp(-((D.^2 - D0^2)./(D.*W + eps)).^2);

(2)陷波带阻和陷波带通滤波器

说明:陷波滤波器是更加有用的选择性滤波器。

实验代码:使用陷波滤波器减少波纹

f = imread('C:\Users\Public\Pictures\Sample Pictures\flower.jpg ');
f=rgb2gray(f);   
[M,N] = size(f);
[f,revertclass] = tofloat(f);
F = fft2(f);
S = fftshift(log(1+abs(F)));    %将直流分量移到频谱中心
S = gscale(S);   %频谱
subplot(221),imshow(f),title('原图像');
subplot(222),imshow(S),title('显示频谱图像');
C1 = [99 154;128 163];         %交互式的尖峰
H1 = cnotch('gaussian', 'reject',M,N,C1,5);      %陷波滤波器
P1 = gscale(fftshift(H1).*(tofloat(S)));         %计算滤波器变换的频谱
subplot(223),imshow(P1), title('滤波变换的频谱图像');
g1 = dftfilt(f,H1);       %滤波图像
g1=revertclass(g1);
subplot(224),imshow(g1), title('滤波图像');

函数gscale:

function g=gscale(f,varargin)
if length(varargin)==0
  method='full8';
else method=varargin{1};
end
if strcmp(class(f),'double')&(max(f(:))>1 | min(f(:))<0)
   f=mat2gray(f);
end

switch method
case 'full8'
        g=im2uint8(mat2gray(double(f)));
case 'full16'
        g=im2uint16(mat2gray(double(f)));
case 'minmax'
       low = varargin{2};high = varargin{3};
       if low>1 | low<0 |high>1 | high<0
             error('Parameters low and high must be in the range [0,1]')
       end
       if strcmp(class(f),'double')
            low_in=min(f(:));
            high_in=max(f(:));
       elseif  strcmp(class(f),'uint8')
            low_in=double(min(f(:)))./255;
            high_in=double(max(f(:)))./255;
       elseif   strcmp(class(f),'uint16')
            low_in=double(min(f(:)))./65535;
            high_in=double(max(f(:)))./65535;
       end
       
       g=imadjust(f,[low_in high_in],[low high]);
otherwise
       error('Unknown method')
end

实验结果:
(图五)
在这里插入图片描述

(图六)
在这里插入图片描述

实验结论:
从图五和图六可以很明显的看出,滤波后的图像波纹减少了,而且图像更加明亮,基本上与原图像没有差别,因此实验证明自适应滤波器的滤波效果更好一些。
从上述图一至图六的对比可以看出,理想高通滤波器会产生振铃效应,滤波效果并不是很好,有点生硬;巴特沃斯高通滤波器和高斯高通滤波器不会产生振铃效应,滤波效果比理想高通滤波器更好一些。但若是加上自适应滤波器,自适应滤波器更加符合我们对图像的处理,因此自适应滤波器会更加普遍。

2019-11-18 16:46:03 donaldsy 阅读数 9

相关理论

几何矩

  • 几何矩 Mji=x,y(P(x,y)xjyi)M_{j i}=\sum_{x, y}\left(P(x, y) \cdot x^{j} \cdot y^{i}\right),其中(i+j)和等于几就叫做几阶距

  • 中心距muji=x,y(P(x,y)(xxˉ)j(yyˉ)i)m u_{j i}=\sum_{x, y}\left(P(x, y) \cdot(x-\bar{x})^{j} \cdot(y-\bar{y})^{i}\right),其中xˉ,yˉ\bar{x}, \bar{y}表示它的中心质点。

  • 中心归一化距nuji=mujim00(i+j)/2+1\mathrm{nu}_{j i}=\frac{\mathrm{mu}_{j i}}{\mathrm{m}_{00}^{(i+j) / 2+1}}

  • 矩的概念介绍

    • 图像中心Center(x0,y0)
      x0=m10m00y0=m01m00\mathrm{x}_{0}=\frac{m_{10}}{m_{00}} y_{0}=\frac{m_{01}}{m_{00}}
  • API介绍与使用-计算矩cv::moments

moments(
    InputArray  array,//输入数据
    bool   binaryImage=false // 是否为二值图像
)

contourArea(
    InputArray  contour,//输入轮廓数据
    bool   oriented// 默认false、返回绝对值
)

arcLength(
    InputArray  curve,//输入曲线数据
    bool   closed// 是否是封闭曲线
)

代码 & 效果展示

  • 演示代码 - 步骤
    • 提取图像边缘
    • 发现轮廓
    • 计算每个轮廓对象的矩
    • 计算每个对象的中心、弧长、面积

相关代码:

#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/types_c.h>

using namespace std;
using namespace cv;

#ifndef P31
#define P31 31
#endif

#if P31 //图形矩形
Mat src, gray_src;
int threshold_value = 80;
int threshold_max = 255;
const char* output_win = "image moents demo";
RNG rng(12345);

void Demo_Moments(int, void*) {
    Mat canny_output;
    vector<vector<Point>> contours;
    vector<Vec4i> hierachy;

    Canny(gray_src, canny_output, threshold_value, threshold_value * 2, 3, false);
    findContours(canny_output, contours, hierachy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));

    vector<Moments> contours_moments(contours.size());
    vector<Point2f> ccs(contours.size());
    for (size_t i = 0; i < contours.size(); i++) {
        contours_moments[i] = moments(contours[i]);
        ccs[i] = Point(static_cast<float>(contours_moments[i].m10 / contours_moments[i].m00), static_cast<float>(contours_moments[i].m01 / contours_moments[i].m00));
    }

    Mat drawImg;// = Mat::zeros(src.size(), CV_8UC3);
    src.copyTo(drawImg);
    for (size_t i = 0; i < contours.size(); i++) {
        if (contours[i].size() < 100) {
            continue;
        }
        Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
        printf("center point x : %.2f y : %.2f\n", ccs[i].x, ccs[i].y);
        printf("contours %d area : %.2f   arc length : %.2f\n", i, contourArea(contours[i]), arcLength(contours[i], true));
        drawContours(drawImg, contours, i, color, 2, 8, hierachy, 0, Point(0, 0));
        circle(drawImg, ccs[i], 2, color,2, 8);
    }

    imshow(output_win, drawImg);
    return;
}
#endif

int main() {
    std::string path = "../circle.JPG";
    cv::Mat img = cv::imread(path, 5);

    string str_input = "input image";
    string str_output = "output image";

    if (img.empty()) {
        std::cout << "open file failed" << std::endl;
        return -1;
    }

    namedWindow(str_input, WINDOW_AUTOSIZE);
    namedWindow(str_output, WINDOW_AUTOSIZE);
    imshow(str_input, img);

#if P31
    src = img;
    cvtColor(src, gray_src, CV_BGR2GRAY);
    GaussianBlur(gray_src, gray_src, Size(3, 3), 0, 0);

    char input_win[] = "input image";
    namedWindow(input_win, WINDOW_AUTOSIZE);
    namedWindow(output_win, WINDOW_AUTOSIZE);
    imshow(input_win, src);

    createTrackbar("Threshold Value : ", output_win, &threshold_value, threshold_max, Demo_Moments);
    Demo_Moments(0, 0);
#endif

    cv::waitKey(0);
    cv::destroyAllWindows();
    return 0;
}

展示效果:
在这里插入图片描述

2016-06-20 17:20:03 u010369450 阅读数 2153

本文为个人入门摘录总结,如有错误请包涵

后续还会加入相应图像代码,因为只是字面上理解,应该存在很多的偏差

比如说Hu矩的基于直角坐标系是指规格化吗?

不变矩(目前只大致学习了经典矩)相关Review如下图


不变矩

简述不变矩及无偏估计与有偏估计

矩描述子类似于力学的求质量,中心转动惯量等,具备不受平移旋转等影响的优点。

设A'=g(X1,X2,...,Xn)是未知参数A的一个点估计量,若A'满足
E(A')= A
则称A'为A的无偏估计量,否则为有偏估计量


矩的定义


p+q阶原点矩:

p+q阶中心矩:
在图像处理中因为图像是一个个像素组合而成,因此应该使用离散形式,在此不再赘述。

矩的规格化(归一化)即将中心矩用零阶中心矩来规格化:
归一化的原因:直接使用普通矩或者中心矩进行特征表示,不能使特征同时具有平移,旋转以及比例不变性,如果利用归一化中心矩,则特征不仅具备平移不变性,而且还具备比例不变性

矩特征表征了图像区域的几何特征又称为几何矩,因为具备旋转,平移以及尺度等特征的不变特征,因此称为不变特征
称为不变矩。
几何不变矩可以用来作为重要的特征来表示物体,进行相关分类,在人形识别常用的不变矩主要有Hu矩Zernike矩

Hu矩

Hu于1961年首先提出了基于直角坐标系的规则矩的概念(来自文章Pattern Recognition by Moment Invariants),之后运用规则矩的非线性组合得到了一套具备尺度不变性,平移不变性以及旋转不变性的矩不变量(来自文章Visual Pattern Recognition by Moment Invariant)。(本段还将增补)
Hu矩的定义,基本性质具备平移,旋转缩放不变性的7个不变矩表达式
7个表达式太长不再赘述,这里附上原文链接:
http://read.pudn.com/downloads155/ebook/687948/Pattern%20Recognition%20by%20Moment%20Invariant.pdf
提取Hu矩方案为
1,输入预处理后的图像。2,计算零阶以及一阶矩。3,计算三阶以下中心矩
4,归一化中心矩。 5,计算7个Hu不变矩



Zernike矩

Zernike矩为基于Zernike多项式的正交化函数,所利用的正交多项式集(完备性是指在数学及其相关领域中,当一个对象具有完备性,即它不需要添加任何其他元素,这个对象也可称为完备的或完全的。  正交的完备性在线性空间中就是指构成这个空间的基是相互正交的,即这个空间中所有的向量都可以由这组基线性表出,而且这些基又相互正交.)Zernike矩源自于Teague提出的正交矩思想,相较于Hu矩,其具备良好的旋转不变性,作为正交矩能够构造任意的高阶矩,运算为积分运算,因此对噪声不敏感。

当计算一幅图像的Zernike矩时,以该图像的形心(也称为原点)把像素坐标映射到单位圆内

Zernike矩是图像函数f(x,y)在正交多项式上的投影,其中正交多项式在单位圆内正交

Zernike矩提取方案为:

1,输入预处理后的图像。2,找出目标最小外接矩形。3,计算各阶矩
4,归一化Zernike矩。 

Zernike矩与Hu矩及其应用

1)优点:

不变矩不受旋转以及大小的影响,可以将其应用于识别二维或者三维物体。

2)缺点:

①不变矩对噪声很敏感,因此有其他作者提出相关不变矩对上述进行改进。

②矩计算时间比较长。

③矩是一种整体性质,如果物体的一部分被其他物体遮挡,则无法计算不变矩。比如说角点是一种描述局部的性质

④Hu提出的不变矩只能对区域进行检测,不能用于边界的检测;对于区域的检测,总体上来说,极半径不变矩与Hu矩的效果相当;但是Hu矩收到图形对称性的影响,而极半径不变矩不受到图形对称性的影响,所以对于对称图形来说,极半径不变矩的效果要优于Hu不变矩

3)应用:

Hu和Zernike矩都具备平移旋转以及缩放的不变性,但是各有特点。Hu的目标信息不是很全面,含有较多的冗余信息;Zernike矩是正交矩,能够构造出任意的高阶矩,包含信息全面,对噪声不敏感。可采用不变矩应用于人形识别算法。


Harris角点检测

Harris角点检测由Chris Harris和Mike Stephens于1988年在A COMBINED CORNER AND EDGE DETECTOR一文中提出

角点检测基础

图像变化类型:

有几何变换和灰度变换。

几何变换又可以分为旋转,仿射(非各项同性的缩放)以及相似(各项同性的缩放)

特征点提取的作用:

是许多计算机视觉算法的基础——使用特征点来代表图像的内容
运动目标跟踪
物体识别
图像配准
全景图像拼接
三维重建

角点的定义以及发展:

角点:

最直观的印象就是在水平、竖直两个方向上变化均较大的点,即Ix、Iy都较大
边缘:仅在水平、或者仅在竖直方向有较大的变化量,即Ix和Iy只有其一较大
平坦地区:在水平、竖直方向的变化量均较小,即Ix、Iy都较小

好的角点算法定义:

检测出图像中“真实的”角点
准确的定位性能
很高的重复检测率(稳定性好)
具有对噪声的鲁棒性
具有较高的计算效率


角点算法的发展:典型的角点检测算法有Harris算法以及CSS算法


其中Harris算法由Chris Harris和Mike Stephens于1988年在A COMBINED CORNER AND EDGE DETECTOR一文中提出

Harris角点算法思想以及实现

Harris角点算法思想:

由局部小窗口观察图像特征,角点定义:窗口向任意方向的移动都导致图像灰度的明显变化

Harris角点性质:

更多角点评价:Evaluation of Interest Point Detectors(IJCV 2000)

具备旋转不变性(椭圆转过一定角度,但是其形状保持不变,即特征值保持不变,角点响应函数R对于图像的旋转具备不变性)

对于图像灰度的仿射变化具备部分的不变性(只使用了图像导数,对于灰度平移变化不变,对于图像灰度的尺度变化

对于尺度变换不具备不变性

Harris角点的实现:定义了灰度变化函数(窗函数*灰度平移前后变化差的平方)以及角点响应函数R

灰度平移前后变化差可以进行泰勒展开,取二阶导及以后项为极小项,相减后即可以得到一个窗口响应函数,根据窗口响应函数分布根据窗口响应函数可以定义角点响应函数R=det M - k(trace M)²【这块的推导应该进行相关研究。 对角点响应函数的理解?

算法:首先对角点响应函数R进行阈值处理(R>threshold)然后提取R的局部极大值




图像对焦区域检测

阅读数 1556

没有更多推荐了,返回首页