基于OpenCV的Harris角点检测
c++的opencv使用方法总结
C++的OpenCV使用方法总结在计算机视觉和图像处理领域,OpenCV是一个非常强大的开源库,它提供了丰富的功能和工具,用于处理图像和视频。
作为C++程序员,了解并熟练使用OpenCV库是非常重要的。
本文将对C++中使用OpenCV的方法进行总结,并探讨一些常见的应用和技巧。
一、安装和配置OpenCV在开始使用OpenCV之前,首先需要安装和配置这个库。
在Windows评台上,可以通过下载预编译的二进制文件进行安装;在Linux评台上,可以通过包管理器进行安装。
安装完毕后,还需进行一些环境配置,确保编译器能够正确信息OpenCV库文件。
二、基本图像处理1. 读取和显示图像在C++中使用OpenCV读取和显示图像非常简单,只需几行代码即可完成。
首先需要使用imread函数读取图像文件,然后使用imshow 函数显示图像。
在进行图像显示后,需要使用waitKey函数等待用户按下某个键,以便关闭显示窗口。
2. 图像的基本操作OpenCV提供了丰富的图像处理函数,包括图像缩放、旋转、平移、通道拆分与合并等。
这些函数可以帮助我们对图像进行各种基本操作,从而满足不同的需求。
三、特征提取与描述1. Harris角点检测Harris角点检测是一种经典的特征点检测方法,它可以用来识别图像中的角点。
在OpenCV中,我们可以使用cornerHarris函数来实现Harris角点检测,然后对检测结果进行筛选和标记。
2. SIFT特征提取SIFT是一种广泛应用的特征提取算法,它具有旋转不变性和尺度不变性。
在OpenCV中,我们可以使用SIFT算法来提取图像的关键点和特征描述子,从而实现图像匹配和目标识别等功能。
四、图像分类与识别1. 使用支持向量机(SVM)进行图像分类OpenCV提供了对机器学习算法的支持,包括SVM分类器。
我们可以使用SVM对图像进行分类,从而实现图像识别和目标检测等功能。
2. 使用深度学习模型进行图像识别近年来,深度学习在图像识别领域取得了显著的成就。
Harris,Shi-Tomasi角点检测与亚像素角点检测笔记
Harris,Shi-Tomasi⾓点检测与亚像素⾓点检测笔记⾓点检测1. ⾓点可以是两个边缘的⾓点;2. ⾓点是邻域内具有两个主⽅向的特征点;⽬录基本思想在各个⽅向上移动窗⼝,若灰度均发⽣了较⼤的变化,那么就认为在窗⼝内遇到了⾓点。
(图3)如果窗⼝在图像各个⽅向上移动时,窗⼝内图像的灰度没有发⽣变化,那么窗⼝内就不存在⾓点。
(图1)如果窗⼝在某⼀个⽅向移动时,窗⼝内图像的灰度发⽣了较⼤的变化,⽽在另⼀些⽅向上没有发⽣变化,那么,窗⼝内的图像可能就是⼀条直线的线段。
(图2)Harris数学模型上⾯的⾃相关函数\(c(x,y;\Delta x,\Delta y)\)表⽰窗⼝W平移\((\Delta x,\Delta y)\)后产⽣的灰度变化。
若对于任何\((\Delta x,\Delta y)\),⾃相关函数c的值均较⼤,则说明该窗⼝内存在⾓点。
上⾯的M矩阵为x,y⽅向的梯度变化。
注意:此时还不能说M为梯度变化协⽅差矩阵,A,B,C不是⽅差和协⽅差。
因此需要进⾏均值化处理:将各维随机变量(这⾥为\ (I_x,I_y\)两维)减去其均值,使处理后的随机变量的均值为0。
接下来就可以进⾏主成分分析。
假设下⾯的\((I_x,I_y)\)已经进⾏过均值化处理,则此时M即为梯度分布协⽅差矩阵。
针对平坦区域,边缘区域以及⾓点区域三种情形的梯度分布\((I_x,I_y)\)进⾏分析:显然:平坦区域的\((I_x,I_y)\)分布在原点附近,相应的其⾃相关函数c在\((\Delta x,\Delta y)\)相同时较⼩。
边缘区域的\((I_x,I_y)\)在某⼀个⽅向上较为分散,按照PCA来理解应该只有⼀个主⽅向。
⾓点区域的\((I_x,I_y)\)在x,y两个⽅向上分布均较为分散。
对协⽅差矩阵M进⾏对⾓化,则特征值即为主⽅向上的⽅差,对应的特征向量即为主⽅向(详见PCA原理)。
得出结论:特征值都⽐较⼤时,即窗⼝中含有⾓点特征值⼀个较⼤,⼀个较⼩,窗⼝中含有边缘特征值都⽐较⼩,窗⼝处在平坦区域在实际判断⾓点时,⽆需计算矩阵M的特征值,使⽤下式近似计算⾓点响应值:\[R=detM - \alpha (traceM)^2 \\ detM = \lambda_1\lambda_2 = AB-C^2 \\ traceM = \lambda_1 + \lambda_2 = A+B \] \(\alpha\)为⼀常数,通常取0.04~0.06.使⽤matlab绘制响应值函数图像如下:则可以发现,该函数图像刚好满⾜协⽅差矩阵M特征值与⾓点的关系:MATLAB代码如下:x = linspace(0,10);y = linspace(0,10);[X,Y] = meshgrid(x,y);Z = X.*Y - 0.05*(X+Y).^2;contour(X,Y,Z,'ShowText','on');xlabel("\lambda_1");ylabel("\lambda_2");算法实现性质1. 参数α对⾓点检测的影响:增⼤α的值,将减⼩⾓点响应值R,减少被检测⾓点的数量;减⼩α的值,将增⼤⾓点响应值R,增加被检测⾓点的数量。
基于Harris原理的亚像素角点坐标检测Matlab程序
基于Harris原理的亚像素角点坐标检测Matlab程序★注意:直接运行click_calib .m文件即可获得亚像素级角点坐标,附录Ⅱ中的其它函数文件均会被click_calib .m文件调用。
click_calib .m %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % 测量亚像素角点坐标的主函数var2fix = 'dX_default';fixvariable; % 调用fixvariable.m文件,修正变量var2fix = 'dY_default';fixvariable;var2fix = 'map';fixvariable;if ~exist('n_ima'),data_calib; % 调用data_calib.m文件,输入图像名和格式,%检查文件中的图像并读取标定图像信息end;check_active_images; % 调用check_active_images.m文件,检查是%否已读取到标定图像if ~exist(['I_' num2str(ind_active(1))]),ima_read_calib;if isempty(ind_read),disp('Cannot extract corners without images');return;end;end;fprintf(1,'\nExtraction of the grid corners on the images\n');if (exist('map')~=1), map = gray(256);end;if exist('dX'),dX_default = dX;end;if exist('dY'),dY_default = dY;end;if exist('n_sq_x'),n_sq_x_default = n_sq_x;end;if exist('n_sq_y'),n_sq_y_default = n_sq_y;end;if ~exist('dX_default')|~exist('dY_default');dX_default = 30;dY_default = 30; % 设靶标平面X和Y方向上方格的默认距离%为30mmend;if ~exist('n_sq_x_default')|~exist('n_sq_y_default'),n_sq_x_default = 10;n_sq_y_default = 10; % 设在靶标平面的x和y方向上提取的角点%数的默认值均为10end;if ~exist('wintx_default')|~exist('winty_default'),wintx_default = max(round(nx/128),round(ny/96));winty_default = wintx_default;clear wintx wintyend;if ~exist('wintx') | ~exist('winty'),clear_windows; % 调用clear_windows.m文件,清除窗口end;if ~exist('dont_ask'),dont_ask = 0;end;if ~dont_ask,ima_numbers = input('Number(s) of image(s) to process ([] = all images) = '); elseima_numbers = [];end;if isempty(ima_numbers),ima_proc = 1:n_ima;elseima_proc = ima_numbers;end;kk_first = ima_proc(1); % 输入('Start image number ([]=1=first): '); if exist(['wintx_' num2str(kk_first)]),eval(['wintxkk = wintx_' num2str(kk_first) ';']);if isempty(wintxkk) | isnan(wintxkk),disp('Window size for corner finder (wintx and winty):');wintx = input(['wintx ([] = ' num2str(wintx_default) ') = ']);if isempty(wintx), wintx = wintx_default; end;wintx = round(wintx);winty = input(['winty ([] = ' num2str(winty_default) ') = ']);if isempty(winty), winty = winty_default; end;winty = round(winty);fprintf(1,'Window size = %dx%d\n',2*wintx+1,2*winty+1);end;elsedisp('Window size for corner finder (wintx and winty):');wintx = input(['wintx ([] = ' num2str(wintx_default) ') = ']);if isempty(wintx), wintx = wintx_default; end;wintx = round(wintx);winty = input(['winty ([] = ' num2str(winty_default) ') = ']);if isempty(winty), winty = winty_default; end;winty = round(winty);fprintf(1,'Window size = %dx%d\n',2*wintx+1,2*winty+1);end;if ~dont_ask,fprintf(1,'Do you want to use the automatic square counting mechanism(0=[]=default)\n');manual_squares = input(' or do you always want to enter the number of squares manually (1,other)? ');if isempty(manual_squares),manual_squares = 0;elsemanual_squares = ~~manual_squares;end;elsemanual_squares = 0;end;for kk = ima_proc,if exist(['I_' num2str(kk)]),click_ima_calib; % 调用click_ima_calib.m文件,点击图像边%界的4个顶点,从而划出边线active_images(kk) = 1;elseeval(['dX_' num2str(kk) ' = NaN;']);eval(['dY_' num2str(kk) ' = NaN;']);eval(['wintx_' num2str(kk) ' = NaN;']);eval(['winty_' num2str(kk) ' = NaN;']);eval(['x_' num2str(kk) ' = NaN*ones(2,1);']);eval(['X_' num2str(kk) ' = NaN*ones(3,1);']);eval(['n_sq_x_' num2str(kk) ' = NaN;']);eval(['n_sq_y_' num2str(kk) ' = NaN;']);end;end;check_active_images;for kk = 1:n_ima,if ~exist(['x_' num2str(kk)]),eval(['dX_' num2str(kk) ' = NaN;']);eval(['dY_' num2str(kk) ' = NaN;']);eval(['x_' num2str(kk) ' = NaN*ones(2,1);']);eval(['X_' num2str(kk) ' = NaN*ones(3,1);']);eval(['n_sq_x_' num2str(kk) ' = NaN;']);eval(['n_sq_y_' num2str(kk) ' = NaN;']);end;if ~exist(['wintx_' num2str(kk)]) | ~exist(['winty_' num2str(kk)]),eval(['wintx_' num2str(kk) ' = NaN;']);eval(['winty_' num2str(kk) ' = NaN;']);end;end;string_save = 'save calib_data active_images ind_active wintx winty n_imatype_numbering N_slots first_num image_numbers format_image calib_name Hcal Wcal nx ny map dX_default dY_default dX dY wintx_default winty_default';for kk = 1:n_ima,string_save = [string_save ' X_' num2str(kk) ' x_' num2str(kk) ' n_sq_x_'num2str(kk) ' n_sq_y_' num2str(kk) ' wintx_' num2str(kk) ' winty_' num2str(kk) ' dX_' num2str(kk) ' dY_' num2str(kk)];end;eval(string_save);disp('done');for lamp = 1:Nima_validdog1=['x_' num2str(lamp)];name1=['x' num2str(lamp) '.txt'];save( name1,dog1,'-ascii');dog2=['X_' num2str(lamp)];name2=['M' num2str(lamp) '.txt'];save( name2,dog2,'-ascii');endreturn; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%fixvariable .m %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % 修正变量if exist('var2fix')==1,if eval(['exist(''' var2fix ''') == 1']),if eval(['isempty(' var2fix ')']),eval(['clear ' var2fix ]);elseif eval(['~isstruct(' var2fix ')']),if eval(['~iscell(' var2fix ')']),if eval(['isnan(' var2fix '(1))']),eval(['clear ' var2fix ]);end;end;end;end;end;end; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%data_calib .m %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % 人工输入图像基名和格式,寻找、读取并显示出所有标定图像l_ras = dir('*ras');s_ras = size(l_ras,1);l_bmp = dir('*bmp');s_bmp = size(l_bmp,1);l_tif = dir('*tif');s_tif = size(l_tif,1);l_pgm = dir('*pgm');s_pgm = size(l_pgm,1);l_ppm = dir('*ppm');s_ppm = size(l_ppm,1);l_jpg = dir('*jpg');s_jpg = size(l_jpg,1);s_tot = s_ras + s_bmp + s_tif + s_pgm + s_jpg + s_ppm;if s_tot < 1,fprintf(1,'No image in this directory in either ras, bmp, tif, pgm, ppm or jpg format. Change directory and try again.\n');break;end;dir;Nima_valid = 0;while (Nima_valid==0),fprintf(1,'\n');calib_name = input('Basename camera calibration images (without number nor suffix): ','s'); % 输入图像基名format_image = '0';while format_image == '0',format_image = input('Image format: ([]=''r''=''ras'', ''b''=''bmp'', ''t''=''tif'',''p''=''pgm'', ''j''=''jpg'', ''m''=''ppm'') ','s'); % 输入图像格式if isempty(format_image),format_image = 'ras';end;if lower(format_image(1)) == 'm',format_image = 'ppm';elseif lower(format_image(1)) == 'b',format_image = 'bmp';elseif lower(format_image(1)) == 't',format_image = 'tif';elseif lower(format_image(1)) == 'p',format_image = 'pgm';elseif lower(format_image(1)) == 'j',format_image = 'jpg';elseif lower(format_image(1)) == 'r',format_image = 'ras';elsedisp('Invalid image format');format_image = '0'; % Ask for format once againend;end;end;end;end;end;end;check_directory; % 调用check_directory .m文件,按图像基名%和格式检查文件中的图像end;if (Nima_valid~=0),ima_read_calib; % 调用ima_read_calib .m文件,读取图像if ~isempty(ind_read),mosaic; % 调用mosaic .m文件,显示所有的标定图像end;end; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%check_directory .m %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % 检查文件中是否存在标定图像l = dir([calib_name '*']);% 返回含calib_name的所有文件信息的一个结构数组n*1 Nl = size(l,1); % Nl为图像的幅数Nima_valid = 0;ind_valid = [];loc_extension = [];length_name = size(calib_name,2); % calib_name的长度if Nl > 0,for pp = 1:Nl,filenamepp = l(pp).name; %第pp幅图像的名字if isempty(calib_name),iii = 1;elseiii = findstr(filenamepp,calib_name);end;loc_ext = findstr(filenamepp,format_image);string_num = filenamepp(length_name+1:loc_ext - 2);if isempty(str2num(string_num)),iii = [];end;if ~isempty(iii), %如果iii非空if (iii(1) ~= 1), %又如果iii(1) != 1,则将iii置空iii = [];end;end;if ~isempty(iii) & ~isempty(loc_ext),Nima_valid = Nima_valid + 1;ind_valid = [ind_valid pp]; %第几个文件的下标是正确的loc_extension = [loc_extension loc_ext(1)];end;end;if (Nima_valid==0),format_image = upper(format_image);for pp = 1:Nl,filenamepp = l(pp).name;if isempty(calib_name),iii = 1;elseiii = findstr(filenamepp,calib_name);end;loc_ext = findstr(filenamepp,format_image);string_num = filenamepp(length_name+1:loc_ext - 2);if isempty(str2num(string_num)),iii = [];end;if ~isempty(iii),if (iii(1) ~= 1),iii = [];end;end;if ~isempty(iii) & ~isempty(loc_ext),Nima_valid = Nima_valid + 1;ind_valid = [ind_valid pp];loc_extension = [loc_extension loc_ext(1)];end;end;if (Nima_valid==0),fprintf(1,'No image found. File format may be wrong.\n');elsestring_length = zeros(1,Nima_valid);indices = zeros(1,Nima_valid);for ppp = 1:Nima_valid,name = l(ind_valid(ppp)).name;string_num = name(length_name+1:loc_extension(ppp) - 2);string_length(ppp) = size(string_num,2);%数字的长度indices(ppp) = str2num(string_num);%数字的大小--下标的顺序end;first_num = min(indices);n_ima = max(indices) - first_num + 1;if min(string_length) == max(string_length),N_slots = min(string_length);type_numbering = 1;elseN_slots = 1;type_numbering = 0;end;image_numbers = first_num:n_ima-1+first_num;active_images = ones(1,n_ima);end;elsestring_length = zeros(1,Nima_valid);indices = zeros(1,Nima_valid);for ppp = 1:Nima_valid,name = l(ind_valid(ppp)).name;string_num = name(length_name+1:loc_extension(ppp) - 2);string_length(ppp) = size(string_num,2);indices(ppp) = str2num(string_num);end;first_num = min(indices);n_ima = max(indices) - first_num + 1;if min(string_length) == max(string_length),N_slots = min(string_length);type_numbering = 1;N_slots = 1;type_numbering = 0;end;image_numbers = first_num:n_ima-1+first_num;active_images = ones(1,n_ima);end;elsefprintf(1,'No image found. Basename may be wrong.\n');end; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%ima_read_calib .m %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % 读取标定图像if ~exist('calib_name')|~exist('format_image'),data_calib;return;end;check_directory;if ~exist('n_ima'),data_calib;return;end;check_active_images; % 调用check_active_images .m文件,检查有效的标定图像images_read = active_images;if exist('image_numbers'),first_num = image_numbers(1);end;if ~exist('first_num'),first_num = image_numbers(1); %第一副图像的数字end;image_numbers = first_num:n_ima-1+first_num;no_image_file = 0;i = 1;while (i <= n_ima), % & (~no_image_file),if active_images(i),if ~type_numbering,number_ext = num2str(image_numbers(i));elsenumber_ext = sprintf(['%.' num2str(N_slots) 'd'],image_numbers(i));end;ima_name = [calib_name number_ext '.' format_image];if i == ind_active(1),fprintf(1,'Loading image ');if exist(ima_name),fprintf(1,'%d...',i);if format_image(1) == 'p',if format_image(2) == 'p',Ii = double(loadppm(ima_name));elseIi = double(loadpgm(ima_name));end;elseif format_image(1) == 'r',Ii = readras(ima_name);elseIi = double(imread(ima_name));end;end;if size(Ii,3)>1,Ii = 0.299 * Ii(:,:,1) + 0.5870 * Ii(:,:,2) + 0.114 * Ii(:,:,3);end;eval(['I_' num2str(i) ' = Ii;']);elseimages_read(i) = 0; %如果ima_name不存在,则设images_read(i)=0;end;end;i = i+1;end;ind_read = find(images_read);if isempty(ind_read),fprintf(1,'\nWARNING! No image were read\n');no_image_file = 1;elseif no_image_file,end;fprintf(1,'\n');if size(I_1,1)~=480,small_calib_image = 1;elsesmall_calib_image = 0;end;[Hcal,Wcal] = size(I_1); % size of the calibration image[ny,nx] = size(I_1); %ny为行数,nx为列数clickname = [];map = gray(256);disp('done');end;if ~(exist('map')==1), map = gray(256); end;active_images = images_read; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Mosaic .m %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % 显示所有查找到的标定图像if ~exist('I_1'),active_images_save = active_images;ima_read_calib;active_images = active_images_save;check_active_images;end;check_active_images;if isempty(ind_read),return;end;n_col = floor(sqrt(n_ima*nx/ny));n_row = ceil(n_ima / n_col);ker2 = 1;for ii = 1:n_col,ker2 = conv(ker2,[1/4 1/2 1/4]);%与[1/4,1/2,1/4]卷积n_col次end;II = I_1(1:n_col:end,1:n_col:end);[ny2,nx2] = size(II);kk_c = 1;II_mosaic = [];for jj = 1:n_row,II_row = [];for ii = 1:n_col,if (exist(['I_' num2str(kk_c)])) & (kk_c <= n_ima),if active_images(kk_c),eval(['I = I_' num2str(kk_c) ';']);I = I(1:n_col:end,1:n_col:end);elseI = zeros(ny2,nx2);end;elseI = zeros(ny2,nx2);end;II_row = [II_row I];if ii ~= n_col,II_row = [II_row zeros(ny2,3)];end;kk_c = kk_c + 1;end;nn2 = size(II_row,2);if jj ~= n_row,II_row = [II_row; zeros(3,nn2)];end;II_mosaic = [II_mosaic ; II_row];end;figure(2);image(II_mosaic);colormap(gray(256));title('Calibration images');set(gca,'Xtick',[])set(gca,'Ytick',[])axis('image'); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%check_active_image .m %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % 检查是否存在有效的标定图像if n_ima ~= 0,if ~exist('active_images'),active_images = ones(1,n_ima);end;n_act = length(active_images);if n_act < n_ima,active_images = [active_images ones(1,n_ima-n_act)];elseif n_act > n_ima,active_images = active_images(1:n_ima);end;end;ind_active = find(active_images);if prod(double(active_images == 0)),disp('Error: There is no active image. Run Add/Suppress images to add images');breakend;if exist('center_optim'),center_optim = double(center_optim);end;if exist('est_alpha'),est_alpha = double(est_alpha);end;if exist('est_dist'),est_dist = double(est_dist);end;if exist('est_fc'),est_fc = double(est_fc);end;if exist('est_aspect_ratio'),est_aspect_ratio = double(est_aspect_ratio);end;end; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%clear_windows .m %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % 清除窗口for kk = 1:n_ima,eval(['clear wintx_' num2str(kk)]);eval(['clear winty_' num2str(kk)]);end; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%click_ima_calib .m %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % 用鼠标点击图像的4个边界点进而划出图像的边界线,检测角点的位置、调用ginput3函数求解像素级角点坐标并使其作为初始值再调用cornerfinder函数求解亚像素角点坐标fprintf(1,'\nProcessing image %d...\n',kk);eval(['I = I_' num2str(kk) ';']);if exist(['wintx_' num2str(kk)]),eval(['wintxkk = wintx_' num2str(kk) ';']);if ~isempty(wintxkk) & ~isnan(wintxkk),eval(['wintx = wintx_' num2str(kk) ';']);eval(['winty = winty_' num2str(kk) ';']);end;end;fprintf(1,'Using (wintx,winty)=(%d,%d) - Window size = %dx%d (Note: To reset the window size, run script clearwin)\n',wintx,winty,2*wintx+1,2*winty+1); figure(2);image(I);colormap(map);set(2,'color',[1 1 1]);title(['Click on the four extreme corners of the rectangular pattern (first corner = origin)... Image ' num2str(kk)]);disp('Click on the four extreme corners of the rectangular complete pattern (the firstclicked corner is the origin)...');x= [];y = [];figure(2); hold on;for count = 1:4,[xi,yi] = ginput3(1);[xxi] = cornerfinder([xi;yi],I,winty,wintx);xi = xxi(1);yi = xxi(2);figure(2);plot(xi,yi,'+','color',[ 1.000 0.314 0.510 ],'linewidth',2);plot(xi + [wintx+.5 -(wintx+.5) -(wintx+.5) wintx+.5 wintx+.5],yi + [winty+.5 winty+.5 -(winty+.5) -(winty+.5) winty+.5],'-','color',[ 1.000 0.3140.510 ],'linewidth',2);x = [x;xi];y = [y;yi];plot(x,y,'-','color',[ 1.000 0.314 0.510 ],'linewidth',2);drawnow;end;plot([x;x(1)],[y;y(1)],'-','color',[ 1.000 0.314 0.510 ],'linewidth',2);drawnow;hold off;[Xc,good,bad,type] = cornerfinder([x';y'],I,winty,wintx); % the four cornersx = Xc(1,:)';y = Xc(2,:)';x_mean = mean(x);y_mean = mean(y);x_v = x - x_mean;y_v = y - y_mean;theta = atan2(-y_v,x_v);[junk,ind] = sort(theta);[junk,ind] = sort(mod(theta-theta(1),2*pi));ind = ind([4 3 2 1]); %-> New: the Z axis is pointing uppwardx = x(ind);y = y(ind);x1= x(1); x2 = x(2); x3 = x(3); x4 = x(4);y1= y(1); y2 = y(2); y3 = y(3); y4 = y(4);p_center = cross(cross([x1;y1;1],[x3;y3;1]),cross([x2;y2;1],[x4;y4;1]));x5 = p_center(1)/p_center(3);y5 = p_center(2)/p_center(3);x6 = (x3 + x4)/2;y6 = (y3 + y4)/2;x7 = (x1 + x4)/2;y7 = (y1 + y4)/2;vX = [x6-x5;y6-y5];vX = vX / norm(vX);vY = [x7-x5;y7-y5];vY = vY / norm(vY);vO = [x4 - x5; y4 - y5];vO = vO / norm(vO);delta = 30;figure(2);image(I);colormap(map);hold on;plot([x;x(1)],[y;y(1)],'g-');plot(x,y,'og');hx=text(x6 + delta * vX(1) ,y6 + delta*vX(2),'X');set(hx,'color','g','Fontsize',14);hy=text(x7 + delta*vY(1), y7 + delta*vY(2),'Y');set(hy,'color','g','Fontsize',14);hO=text(x4 + delta * vO(1) ,y4 + delta*vO(2),'O','color','g','Fontsize',14);hold off;if manual_squares,n_sq_x = input(['Number of squares along the X direction ([]='num2str(n_sq_x_default) ') = ']);if isempty(n_sq_x), n_sq_x = n_sq_x_default; end;n_sq_y = input(['Number of squares along the Y direction ([]='num2str(n_sq_y_default) ') = ']);if isempty(n_sq_y), n_sq_y = n_sq_y_default; end;elsen_sq_x1 = count_squares(I,x1,y1,x2,y2,wintx);n_sq_x2 = count_squares(I,x3,y3,x4,y4,wintx);n_sq_y1 = count_squares(I,x2,y2,x3,y3,wintx);n_sq_y2 = count_squares(I,x4,y4,x1,y1,wintx);if (n_sq_x1~=n_sq_x2)|(n_sq_y1~=n_sq_y2),disp('Could not count the number of squares in the grid. Enter manually.');n_sq_x = input(['Number of squares along the X direction ([]='num2str(n_sq_x_default) ') = ']);if isempty(n_sq_x), n_sq_x = n_sq_x_default; end;n_sq_y = input(['Number of squares along the Y direction ([]='num2str(n_sq_y_default) ') = ']); %6if isempty(n_sq_y), n_sq_y = n_sq_y_default; end;elsen_sq_x = n_sq_x1;n_sq_y = n_sq_y1;end;end;n_sq_x_default = n_sq_x;n_sq_y_default = n_sq_y;if (exist('dX')~=1)|(exist('dY')~=1),dX = input(['Size dX of each square along the X direction ([]='num2str(dX_default) 'mm) = ']);dY = input(['Size dY of each square along the Y direction ([]='num2str(dY_default) 'mm) = ']);if isempty(dX), dX = dX_default; else dX_default = dX; end;if isempty(dY), dY = dY_default; else dY_default = dY; end;elsefprintf(1,['Size of each square along the X direction: dX=' num2str(dX) 'mm\n']);fprintf(1,['Size of each square along the Y direction: dY=' num2str(dY) 'mm (Note: To reset the size of the squares, clear the variables dX and dY)\n']);end;a00 = [x(1);y(1);1];a10 = [x(2);y(2);1];a11 = [x(3);y(3);1];a01 = [x(4);y(4);1];[Homo,Hnorm,inv_Hnorm] = compute_homography([a00 a10 a11 a01],[0 1 1 0;0 0 1 1;1 1 1 1]);x_l = ((0:n_sq_x)'*ones(1,n_sq_y+1))/n_sq_x;y_l = (ones(n_sq_x+1,1)*(0:n_sq_y))/n_sq_y;pts = [x_l(:) y_l(:) ones((n_sq_x+1)*(n_sq_y+1),1)]';XX = Homo*pts;XX = XX(1:2,:) ./ (ones(2,1)*XX(3,:));W = n_sq_x*dX;L = n_sq_y*dY;figure(2);hold on;plot(XX(1,:),XX(2,:),'r+');title('The red crosses should be close to the image corners');hold off;disp('If the guessed grid corners (red crosses on the image) are not close to the actual corners,');disp('it is necessary to enter an initial guess for the radial distortion factor kc (useful for subpixel detection)');quest_distort = input('Need of an initial guess for distortion? ([]=no, other=yes) '); quest_distort = ~isempty(quest_distort);if quest_distort,c_g = [size(I,2);size(I,1)]/2 + .5;f_g = Distor2Calib(0,[[x(1) x(2) x(4) x(3)] - c_g(1);[y(1) y(2) y(4) y(3)] -c_g(2)],1,1,4,W,L,[-W/2 W/2 W/2 -W/2;L/2 L/2 -L/2 -L/2; 0 0 0 0],100,1,1);f_g = mean(f_g);script_fit_distortion;end;Np = (n_sq_x+1)*(n_sq_y+1);disp('Corner extraction...');grid_pts = cornerfinder(XX,I,winty,wintx);grid_pts = grid_pts - 1; % subtract 1 to bring the origin to (0,0) instead of (1,1) in matlab (not necessary in C)ind_corners = [1 n_sq_x+1 (n_sq_x+1)*n_sq_y+1 (n_sq_x+1)*(n_sq_y+1)]; % index of the 4 cornersind_orig = (n_sq_x+1)*n_sq_y + 1;xorig = grid_pts(1,ind_orig);yorig = grid_pts(2,ind_orig);dxpos = mean([grid_pts(:,ind_orig) grid_pts(:,ind_orig+1)]');dypos = mean([grid_pts(:,ind_orig) grid_pts(:,ind_orig-n_sq_x-1)]');x_box_kk =[grid_pts(1,:)-(wintx+.5);grid_pts(1,:)+(wintx+.5);grid_pts(1,:)+(wintx+.5);grid_pts(1 ,:)-(wintx+.5);grid_pts(1,:)-(wintx+.5)];y_box_kk =[grid_pts(2,:)-(winty+.5);grid_pts(2,:)-(winty+.5);grid_pts(2,:)+(winty+.5);grid_pts(2, :)+(winty+.5);grid_pts(2,:)-(winty+.5)];figure(3);image(I); colormap(map); hold on;plot(grid_pts(1,:)+1,grid_pts(2,:)+1,'r+');plot(x_box_kk+1,y_box_kk+1,'-b');plot(grid_pts(1,ind_corners)+1,grid_pts(2,ind_corners)+1,'mo');plot(xorig+1,yorig+1,'*m');h = text(xorig+delta*vO(1),yorig+delta*vO(2),'O');set(h,'Color','m','FontSize',14);h2 = text(dxpos(1)+delta*vX(1),dxpos(2)+delta*vX(2),'dX');set(h2,'Color','g','FontSize',14);h3 = text(dypos(1)+delta*vY(1),dypos(2)+delta*vY(2),'dY');set(h3,'Color','g','FontSize',14);xlabel('Xc (in camera frame)');ylabel('Yc (in camera frame)');title('Extracted corners');zoom on;drawnow;hold off;Xi = reshape(([0:n_sq_x]*dX)'*ones(1,n_sq_y+1),Np,1)';Yi = reshape(ones(n_sq_x+1,1)*[n_sq_y:-1:0]*dY,Np,1)';Zi = zeros(1,Np);Xgrid = [Xi;Yi;Zi];x = grid_pts;X = Xgrid;eval(['dX_' num2str(kk) ' = dX;']);eval(['dY_' num2str(kk) ' = dY;']);eval(['wintx_' num2str(kk) ' = wintx;']);eval(['winty_' num2str(kk) ' = winty;']);eval(['x_' num2str(kk) ' = x;']);eval(['X_' num2str(kk) ' = X;']);eval(['n_sq_x_' num2str(kk) ' = n_sq_x;']);eval(['n_sq_y_' num2str(kk) ' = n_sq_y;']); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%ginput3 .m %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %ginput3函数实现了计算划出图像的边界线,同时计算出像素级角点坐标function [out1,out2,out3] = ginput2(arg1)P = NaN*ones(16,16);P(1:15,1:15) = 2*ones(15,15);P(2:14,2:14) = ones(13,13);P(3:13,3:13) = NaN*ones(11,11);P(6:10,6:10) = 2*ones(5,5);P(7:9,7:9) = 1*ones(3,3);out1 = []; out2 = []; out3 = []; y = [];c = computer;if ~strcmp(c(1:2),'PC') & ~strcmp(c(1:2),'MA')tp = get(0,'TerminalProtocol');elsetp = 'micro';endif ~strcmp(tp,'none') & ~strcmp(tp,'x') & ~strcmp(tp,'micro'),if nargout == 1,if nargin == 1,eval('out1 = trmginput(arg1);');elseeval('out1 = trmginput;');endelseif nargout == 2 | nargout == 0,if nargin == 1,eval('[out1,out2] = trmginput(arg1);');elseeval('[out1,out2] = trmginput;');endif nargout == 0out1 = [ out1 out2 ];endelseif nargout == 3,if nargin == 1,eval('[out1,out2,out3] = trmginput(arg1);');elseeval('[out1,out2,out3] = trmginput;');endendelsefig = gcf;figure(gcf);if nargin == 0how_many = -1;b = [];elsehow_many = arg1;b = [];if isstr(how_many) ...| size(how_many,1) ~= 1 | size(how_many,2) ~= 1 ...| ~(fix(how_many) == how_many) ...| how_many < 0error('Requires a positive integer.')endif how_many == 0ptr_fig = 0;while(ptr_fig ~= fig)ptr_fig = get(0,'PointerWindow');endscrn_pt = get(0,'PointerLocation');loc = get(fig,'Position');pt = [scrn_pt(1) - loc(1), scrn_pt(2) - loc(2)];out1 = pt(1); y = pt(2);elseif how_many < 0error('Argument must be a positive integer.')endendpointer = get(gcf,'pointer');set(gcf,'Pointer','custom','PointerShapeCData',P,'PointerShapeHotSpot',[8,8]);fig_units = get(fig,'units');char = 0;while how_many ~= 0waserr = 0;eval('keydown = wfbp;', 'waserr = 1;');if(waserr == 1)if(ishandle(fig))set(fig,'pointer',pointer,'units',fig_units);error('Interrupted');elseerror('Interrupted by figure deletion');endendptr_fig = get(0,'CurrentFigure');if(ptr_fig == fig)if keydownchar = get(fig, 'CurrentCharacter');button = abs(get(fig, 'CurrentCharacter'));scrn_pt = get(0, 'PointerLocation');set(fig,'units','pixels')loc = get(fig, 'Position');pt = [scrn_pt(1) - loc(1), scrn_pt(2) - loc(2)];set(fig,'CurrentPoint',pt);elsebutton = get(fig, 'SelectionType');if strcmp(button,'open')button = 1; %b(length(b));elseif strcmp(button,'normal')button = 1;elseif strcmp(button,'extend')button = 2;elseif strcmp(button,'alt')button = 3;elseerror('Invalid mouse selection.')endendpt = get(gca, 'CurrentPoint');how_many = how_many - 1;if(char == 13) % & how_many ~= 0)break;endout1 = [out1;pt(1,1)];y = [y;pt(1,2)];b = [b;button];endendset(fig,'pointer',pointer,'units',fig_units);if nargout > 1out2 = y;if nargout > 2out3 = b;endelse。
视觉机器应用实验报告(3篇)
第1篇一、实验目的本次实验旨在通过实际操作,了解并掌握视觉机器的基本原理和应用,提高对视觉机器处理技术的认识。
实验内容包括边缘检测、显著性检测、特征点检测和直线检测等,通过对比不同算法的优缺点,分析其在实际图像处理中的应用和局限性。
二、实验内容与步骤1. 边缘检测(1)选择图像数据:选取一张包含明显边缘结构的图像作为实验对象。
(2)Sobel边缘检测:使用Sobel算子对图像进行边缘检测,记录结果。
(3)Canny边缘检测:使用Canny算子对图像进行边缘检测,记录结果。
(4)比较两种方法的边缘检测效果,分析其差异。
2. 显著性检测(1)选择图像数据:选取一张包含不同显著性区域的图像作为实验对象。
(2)HC显著性检测:使用Python和OpenCV实现HC显著性检测算法,调整参数,比较检测效果。
(3)基于最小方向对比度显著性检测:使用Python和OpenCV实现基于最小方向对比度显著性检测算法,调整参数,比较检测效果。
(4)基于最稳定区域显著性检测:使用Python和OpenCV实现基于最稳定区域显著性检测算法,调整参数,比较检测效果。
3. 特征点检测(1)选择图像数据:选取一张包含明显角点的图像作为实验对象。
(2)Harris角点检测:使用Python和OpenCV实现Harris角点检测算法,调整参数,比较检测效果。
(3)分析角点检测结果与实际图像特征之间的关系。
4. 直线检测(1)选择图像数据:选取一张包含直线的图像作为实验对象。
(2)哈夫变换直线检测:使用Python和OpenCV实现哈夫变换直线检测算法,调整参数,比较检测效果。
(3)对图像进行预处理(如边缘检测)以提高直线检测效果。
(4)分析哈夫变换在实际场景中的应用和局限性。
三、实验结果与分析1. 边缘检测通过对比Sobel算子和Canny算子的边缘检测结果,发现Canny算子具有更好的检测效果,能够有效抑制噪声,同时保留边缘信息。
Harris与SUSAN原理及实验结果分析
Harris 与SUSAN 角点检测算法原理与实验结果分析一.Harris 算法原理Harris 角点检测算法的基本原理是取以目标像素点为中心的一个小窗口,计算窗口沿任何方向移动后的灰度变化,并用解析形式表达。
设以像素点(x,y)为中心的小窗口在X 方向上移动u ,y 方向上移动v ,Harris 给出了灰度变化度量的解析表达式:2,,|,|,,()(x y x y x u y v x y x y I I E w I I w u v o X Y ∂∂=-=++∂∂∑∑ (1.1)其中,,x y E 为窗口内的灰度变化度量;,x y w 为窗口函数,一般定义为222()/,x y x y w eσ+=;I 为图像灰度函数,略去无穷小项有: 222222,,[()()2]2x y x y x y x y E w u I v I uvI I Au Cuv Bv =++=++∑(1.2)将,x y E 化为二次型有: ,[]x y u E u v M v ⎡⎤=⎢⎥⎣⎦(1.3)M 为实对称矩阵: 2,2x y x x y x y y I I I M w I I I ∙⎤⎡=⎥⎢∙⎢⎥⎣⎦∑ (1.4)通过对角化处理得到: 11,200x y E R R λλ-⎛⎫= ⎪⎝⎭ (1.5)其中,R 为旋转因子,对角化处理后并不改变以u,v 为坐标参数的空间曲面的形状,其特征值反应了两个主轴方向的图像表面曲率。
当两个特征值均较小时,表明目标点附近区域为“平坦区域”;特征值一大一小时,表明特征点位于“边缘”上;只有当两个特征值均比较大时,沿任何方向的移动均将导致灰度的剧烈变化。
Harris 的角点响应函数(CRF)表达式由此而得到:2(,)det()(())CRF x y M k trace M =- (1.6) 其中:det(M)表示矩阵M 的行列式,trace(M)表示矩阵的迹。
当目标像素点的CRF 值大于给定的阈值时,该像素点即为角点。
特征检测之Harris角点检测简介
特征点又叫兴趣点或者角点。
常被用于目标匹配,目标跟踪,三维重建等应用中。
点特征主要指图像中的明显点,如突出的角点、边缘端点、极值点等等。
特征点具有以下三种特性:▪旋转不变性;▪光照不变性;▪视角不变性。
用于点特征提取的算子称为兴趣点提取(检测)算子。
常用的有▪Harris角点检测;▪FAST特征检测;▪SIFT特征检测;▪SURF特征检测。
预备数学实对称矩阵如果有n阶矩阵A,其矩阵的元素都为实数,且矩阵A的转置等于其本身,则称A为实对称矩阵。
性质:▪实对称矩阵A的不同特征值对应的特征向量是正交的;▪n阶实对称矩阵A必可相似对角化,且相似对角阵上的元素即为矩阵本身特征值。
对角化:优点:满秩的对角方阵,可以直接看出特征值,特征向量等重要特征。
卷积算子—Sobel算子主要用于边缘检测,分别对水平和垂直方向上的边缘敏感。
对图像任意一点使用会产生对应的梯度矢量或者其法矢量。
对噪声具有平滑抑制作用,但是得到的边缘较粗,且可能出现伪边缘。
该算子包含两组3x3的矩阵,分别为横向及纵向,将之与图像作平面卷积,即可分别得出横向及纵向的亮度差分近似值。
如果以A代表原始图像,Gx 及Gy分别代表经横向及纵向边缘检测的图像,其公式如下:梯度计算公式梯度方向计算公式如果等于零,代表图像该处拥有纵向边缘,左边比右边要暗。
基础知识1、角点使用一个滑动窗口在下面三幅图中滑动,可以得出以下结论:▪左图表示一个平坦区域,在各方向移动,窗口内像素值均没有太大变化;▪中图表示一个边缘特征(Edges),如果沿着水平方向移动(梯度方向),像素值会发生跳变;如果沿着边缘移动(平行于边缘) ,像素值不会发生变化;▪右图表示一个角(Corners),不管你把它朝哪个方向移动,像素值都会发生很大变化。
所以,右图是一个角点。
2、角点类型下图展示了不同角点的类型,可以发现:如果使用一个滑动窗口以角点为中心在图像上滑动,存在朝多个方向上的移动会引起该区域的像素值发生很大变化的现象。
Harris角点检测
Harris⾓点检测⽬录OpenCV可以检测图像的主要特征,然后提取这些特征、使其成为图像描述符,这类似于⼈的眼睛和⼤脑。
这些图像特征可作为图像搜索的数据库。
此外,⼈们可以利⽤这些关键点将图像拼接起来,组成⼀个更⼤的图像,⽐如将许多图像放在⼀块,然后形成⼀个360度全景图像。
这⾥我们将学习使⽤OpenCV来检测图像特征,并利⽤这些特征进⾏图像匹配和搜索。
我们会选取⼀些图像,并通过单应性,检测这些图像是否在另⼀张图像中。
⼀特征检测算法有许多⽤于特征检测和提取的算法,我们将会对其中⼤部分进⾏介绍。
OpenCV最常使⽤的特征检测和提取算法有:Harris:该算法⽤于检测⾓点;SIFT:该算法⽤于检测斑点;SURF:该算法⽤于检测⾓点;FAST:该算法⽤于检测⾓点;BRIEF:该算法⽤于检测斑点;ORB:该算法代表带⽅向的FAST算法与具有旋转不变性的BRIEF算法;通过以下⽅法进⾏特征匹配:暴⼒(Brute-Force)匹配法;基于FLANN匹配法;可以采⽤单应性进⾏空间验证。
⼆特征定义那么,究竟什么是特征呢?为什么⼀副图像的某个特定区域可以作为⼀个特征,⽽其他区域不能呢?粗略的讲,特征就是有意义的图像区域,该区域具有独特特征和易于识别性。
因此⾓点及⾼密度区域都是很好的特征,⽽⼤量重复的模式或低密度区域(例如图像中的蓝⾊天空)则不是很好的特征。
边缘可以将图像分为两个区域,因此也可以看做好的特征。
斑点是与周围有很⼤差别的像素区域,也是有意义的特征。
⼤多数特征检测算法都会涉及图像的⾓点、边和斑点的识别,也有⼀些涉及脊向的概念,可以认为脊向是细长物体的对称轴,例如识别图像中的⼀条路。
⾓点和边都好理解,那什么是斑点呢?斑点通常是指与周围有着颜⾊和灰度差别的区域。
在实际地图中,往往存在着⼤量这样的斑点,如⼀颗树是⼀个斑点,⼀块草地是⼀个斑点,⼀栋房⼦也可以是⼀个斑点。
由于斑点代表的是⼀个区域,相⽐单纯的⾓点,它的稳定性要好,抗噪声能⼒要强,所以它在图像配准上扮演了很重要的⾓⾊。
完整版Harris角点检测算法编程步骤及示例演示
Harris 角点检测算法编程步骤及示例演示也不说那么多废话了,要介绍啥背景意义之类的,角点检测,顾名思义,就是检测角点,最简单的就是两条线的交点了,还有比如下国际象棋的棋盘格子的交点之类的,反正就是检测这些点。
简单将Harris 角点检测算法的思想说下,就是拿一个小窗在图像中移动,通过考察这个小窗口内图像灰度的平均变换值来确定角点。
1)如果窗口内区域图像的灰度值恒定,那么所有不同方向的偏移几乎不发生变化;2)如果窗口跨越一条边,那么沿着这条边的偏移几乎不发生变化,但是与边垂直的偏移会发生很大的变化;3)如果窗口包含一个孤立的点或者角点,那么所有不同方向的偏移会发生很大的变化。
面给出具体数学推导:设图像窗口平移量为( u,v) ,产生的灰度变化为E(u,v),有E(u,v)二sum[w(x,y)[l(x+u,y+v)-l(x,y)F2棋中w(x,y)为窗口函数, l(x+u,y+v为平移后的灰度值,l(x,y)为平移前的灰度值。
有泰勒公式展开可得:l(x+u,y+v)=l(x,y)+lx*u+ly*v+0(uA2,v八2);lx,ly分别为偏微分,在图像中为图像的方向导数因此E(u,v)=sum[w(x,y) [lx*u+ly*v+O(u八2,v八2)]八2],可以近似得到E(u,v)=sum[w(x,y) [lx*u+ly*v]^2],即E(u,v)二[u,v][lx八2,lx*ly;lx*ly,ly八2][u,v]T令M=[lx八2,lx*ly;lx*ly,ly八2],因此最后对角点的检测成了对矩阵M的特征值的分析了,令M 其特征值为x1,x2;当x1>>x2或者x2>>x1,则检测到的是边缘部分;当x1,x2都很小,图像窗口在所有移动的方向上移动灰度级都无明显变化.当X1,X2都很大时且相当,检测到的是角点。
编程时用x1,x2不方便,因此定义角点响应函数;R二det(M)-k(trace(M))八2;其中det(M)为矩阵M的行列式,trace(M)为矩阵M的迹。
Harris角点检测原理及实现
Harris⾓点检测原理及实现为便于理解,先简要介绍⾓点的概念和⾓点检测背景1 背景⾓点检测⼤致可分为三类:基于灰度图的⾓点检测、基于⼆值化图像的⾓点检测和基于轮廓曲线的⾓点检测。
Harris属于基于灰度图的⾓点检测。
2 Harris特征原理2.1 概述Harris⾓点检测根据窗⼝向多个⽅向,通过判断窗⼝内像素值有⽆明显变化判断有⽆⾓点。
如下图: 第⼀幅图像中,窗⼝内像素值⽆明显变化,⽆⾓点。
第⼆幅图像中,窗⼝⽔平移动时有明显变化,⽆⾓点。
第三幅图中,窗⼝多个⽅向移动时有明显变化,有⾓点。
Harris⾓点检测可分为三步:梯度计算、响应值计算、⾓点提取。
下⾯按步骤介绍。
2.2梯度计算: 对图像中的任意⼀像素点I(x,y),进⾏⾃相关平移w(x+Δx、y+Δy)得到⾃相关函数: c(x,y,Δx,Δy) = ∑w h(x,y)(I(x,y)-I(x+Δx,y+Δy))2 其中 ∑w表⽰窗⼝内的点,h(x,y)表⽰加权函数,加权函数可根据⾃⼰需要进⾏修改(通过修改源代码)。
由泰勒可得: I(x+Δx,y+Δy) = I(x,y)+ΔxI x(x,y)+ΔyI y(x,y)+p ≈I(x,y)+ΔxI x(x,y)+ΔyI y(x,y)代⼊⾃相关函数可得(加权函数暂时忽略): c(x,y,Δx,Δy) = ∑w(I(x,y)-I(x+Δx,y+Δy))2 ≈ ∑w((ΔxI x(x,y))2+2ΔxΔyI x(x,y)I y(x,y)+(ΔyI y(x,y))2) 将上公式⽤图表⽰如下: 其中,u和v分别表⽰Δx和Δy,w(x,y)表⽰加权函数。
Harris算法是通过判断像素值是否在多个⽅向上有明显变化可转换为为是否在x和y⽅向上像素值均有明显变化,再转换为Ix或Iy的变化,再转换为M矩阵的特征值λ1,λ2的变化,如下图:2.3响应值计算:上⾯计算不易于通过编程实现,Harris通过定义⾓点响应函数R的⽅式,⽤于表⽰⼀个⾓点的Harris响应值:trace表⽰为矩阵的迹,det为矩阵的⾏列式(矩阵的迹:主对⾓线上的值相加即所有特征值的和),k为经验常数,⼀般取0.04~0.06。
harris角点检测算法步骤
harris角点检测算法步骤Harris角点检测算法步骤:一、引言Harris角点检测算法是计算机视觉中常用的角点检测算法之一。
它通过分析图像的局部灰度变化来寻找图像中的角点,被广泛应用于图像处理、物体识别、图像匹配等领域。
本文将介绍Harris角点检测算法的步骤及其原理。
二、灰度处理Harris角点检测算法首先需要将彩色图像转换为灰度图像,这是因为角点检测主要关注图像的灰度变化而非颜色信息。
通过将彩色图像的每个像素的RGB值加权平均,可以得到相应的灰度值。
三、计算梯度接下来,对灰度图像进行梯度计算。
梯度表示图像中的灰度变化,是图像中像素灰度值变化最快的方向。
通过对图像使用Sobel算子或其他梯度计算算法,可以计算出每个像素的梯度幅值和方向。
四、计算结构张量在Harris角点检测算法中,结构张量是一个重要的概念。
对于每个像素点,结构张量是一个2x2的矩阵,它描述了该像素点周围区域的灰度变化情况。
结构张量的计算公式包括对梯度幅值的平方、梯度幅值的乘积以及梯度方向的加权。
五、计算角点响应函数角点响应函数是Harris角点检测算法的核心。
它通过对结构张量进行特征值分解,得到每个像素点的角点响应值。
角点响应值的计算公式是通过特征值的乘积减去特征值的和,再乘以一个经验系数。
如果特征值的乘积较大,说明该像素点是角点。
六、非极大值抑制由于角点响应函数在角点处达到最大值,但在边缘和平坦区域也可能有较大值,为了提取出准确的角点,需要进行非极大值抑制。
在非极大值抑制过程中,对于每个像素点,比较其角点响应值与周围像素点的角点响应值,如果大于周围像素点的角点响应值,则保留,否则抑制。
七、阈值处理为了进一步提取出准确的角点,可以根据角点响应值设置一个阈值。
只有角点响应值大于阈值的像素点才被认为是角点。
阈值的选择是一个关键问题,需要根据具体应用场景和图像特点进行调整。
八、角点标记最后一步是将检测到的角点在原始图像上进行标记。
harris角点检测算法原理
harris角点检测算法原理Harris角点检测算法原理引言:角点检测是计算机视觉中一项重要的任务,它可以帮助计算机识别和跟踪图像中的角点特征。
Harris角点检测算法是一种经典的角点检测方法,它通过计算图像中像素点的角点响应函数来确定角点的位置。
一、角点的定义和特点角点是图像中突然变化的区域,其特点是在多个方向上都具有较大的灰度变化。
由于角点在图像中具有明显的特征,因此检测角点可以帮助计算机识别和跟踪物体。
二、角点响应函数Harris角点检测算法通过计算每个像素点的角点响应函数来确定是否为角点。
角点响应函数的计算公式如下:R = det(M) - k * trace^2(M)其中,M是一个2×2的矩阵,表示像素点附近的灰度变化情况。
det(M)表示矩阵M的行列式,trace(M)表示矩阵M的迹,k是一个常数。
三、角点响应函数的计算步骤1. 图像梯度计算:首先,对图像进行梯度计算,得到每个像素点的梯度幅值和梯度方向。
2. 构建自相关矩阵:对于每个像素点,根据其周围像素点的梯度幅值和梯度方向,构建一个2×2的自相关矩阵M。
3. 计算角点响应函数:根据自相关矩阵M的行列式和迹,计算角点响应函数R。
4. 阈值化和非极大值抑制:对于每个像素点,根据角点响应函数的值,进行阈值化操作,并对超过阈值的像素点进行非极大值抑制。
四、Harris角点检测算法的优缺点1. 优点:(1)计算简单:Harris角点检测算法的计算量相对较小,适合在实时应用中使用。
(2)稳定性好:Harris角点检测算法对图像的旋转、缩放和亮度变化具有较好的稳定性。
(3)可靠性高:Harris角点检测算法在各种场景下都能够较为准确地检测到角点。
2. 缺点:(1)对噪声敏感:Harris角点检测算法对噪声比较敏感,噪声会影响角点的检测结果。
(2)对尺度变化不敏感:Harris角点检测算法对于图像的尺度变化比较不敏感,可能会漏检或误检角点。
opencvpython角点检测函数输出坐标
Opencv python角点检测函数输出坐标OpenCV是一个强大的计算机视觉库,提供了许多图像处理和计算机视觉功能。
在OpenCV中,角点检测是通过Harris角点检测或者SIFT(尺度不变特征变换)等方法来完成的。
在Python中使用OpenCV进行角点检测的基本步骤如下:1. 读取图像2. 转换为灰度图像3. 使用角点检测算法找到角点4. 输出角点坐标下面是一个使用OpenCV进行Harris角点检测并输出角点坐标的Python代码示例:```pythonimport cv2import numpy as np# 读取图像image = cv2.imread('image.jpg')# 转换为灰度图像gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# Harris角点检测参数blockSize = 2aperture = 3winSize = (15,15)# Harris角点检测dst = cv2.cornerHarris(gray, blockSize, aperture, winSize)# 对Harris值进行归一化,使其在0-255之间dst = cv2.normalize(dst, None, 0, 255, cv2.NORM_MINMAX)# 使用阈值确定哪些是角点,阈值可以根据实际情况调整# 这里使用的是3个像素的阈值,即如果某个像素的值大于3*3的窗口中的其他8个像素值,则认为这个像素是角点threshold = 3points = np.uint8(dst > threshold)# 找到角点并输出坐标if points.any():print("找到角点:")for (x, y) in np.where(points == 1):print(f"({x}, {y})")else:print("未找到角点")```在这个示例中,我们首先读取一张图像并将其转换为灰度图像。
harris角点检测算法 题目
harris角点检测算法题目Harris角点检测算法是一种用于检测图像中角点的算法。
角点是图像中具有明显方向变化的地方,通常对应于场景中的边缘或拐点。
Harris角点检测算法具有较好的抗噪声性能和稳健性,因此在计算机视觉和图像处理领域得到了广泛应用。
题目:Harris角点检测算法的实现与应用一、问题描述Harris角点检测算法是一种广泛应用于图像处理和计算机视觉领域的角点检测算法。
该算法通过分析图像局部区域的灰度变化来确定角点位置,具有较好的稳定性和准确性。
本题目要求实现Harris角点检测算法,并探讨其在图像处理和计算机视觉领域的应用。
二、实现步骤1. 导入必要的库和模块,包括NumPy、OpenCV等。
2. 读取待处理的图像,并将其转换为灰度图像。
3. 定义Harris角点检测函数,包括计算图像中每个像素点的Harris响应值和确定角点位置等步骤。
4. 对灰度图像中的每个像素点应用Harris角点检测函数,得到每个像素点的Harris响应值。
5. 根据Harris响应值的大小,确定角点位置,并将其标记在图像上。
6. 可选:对检测到的角点进行可视化展示,以便更好地理解角点位置和分布情况。
三、应用示例1. 特征匹配:利用Harris角点检测算法检测两幅图像中的相似区域,通过特征匹配实现图像拼接、目标跟踪等功能。
2. 运动估计:利用Harris角点检测算法提取视频序列中的关键帧,通过对关键帧中角点的运动轨迹分析,估计视频中物体的运动轨迹和方向。
3. 3D重建:结合Harris角点检测算法和立体视觉技术,从多视角图像中提取角点信息,通过立体匹配和三维重建技术,重建出场景的三维结构。
4. 目标识别:利用Harris角点检测算法提取图像中的角点特征,结合分类器对目标进行识别和分类,如人脸识别、手势识别等。
5. 增强现实:通过Harris角点检测算法确定图像中的特征点位置,将虚拟物体与实际场景中的特征点进行配准,实现增强现实的效果。
opencv的相机标定方法
(原创实用版4篇)编制人员:_______________审核人员:_______________审批人员:_______________编制单位:_______________编制时间:____年___月___日序言下面是本店铺为大家精心编写的4篇《opencv的相机标定方法》,供大家借鉴与参考。
下载后,可根据实际需要进行调整和使用,希望能够帮助到大家,谢射!(4篇)《opencv的相机标定方法》篇1相机标定是计算机视觉中一个重要的问题,它的目的是确定相机的内部参数和外部参数。
在 OpenCV 中,可以使用 cv::calibrateCamera() 函数进行相机标定。
该函数需要输入标定板的角点坐标和相机拍摄到的图像,然后可以计算出相机的内部参数(如焦距、主点坐标等)和外部参数(如相机的旋转和平移矩阵)。
具体地,相机标定的过程可以分为以下几个步骤:1. 准备标定板:标定板应该是一个平面板,上面有一些精确的几何形状(如圆形或棋盘格),以便于在图像中进行角点检测。
2. 拍摄标定板:使用相机拍摄标定板,并获取相机的内部参数和外部参数。
3. 角点检测:在获取到的图像中,使用角点检测算法(如 Harris 角点检测)检测出标定板上的角点。
4. 计算变换矩阵:根据标定板上的角点坐标和相机拍摄到的图像,可以计算出相机的旋转和平移矩阵。
5. 相机标定:使用 cv::calibrateCamera() 函数,将计算出的变换矩阵输入到函数中,即可计算出相机的内部参数和外部参数。
需要注意的是,相机标定的结果可能会受到多种因素的影响,如标定板的形状、大小、标定时的光照条件等。
《opencv的相机标定方法》篇2相机标定是计算机视觉中一个重要的问题,它的目的是确定相机内部参数和外部参数,以便于后续图像处理和计算机视觉任务。
在 OpenCV 中,相机标定可以采用多种方法,其中比较常见的包括:1. 张正友标定法(Zhang Z. et al. A flexible camera calibration method for non-coplanar cameras. ICCV 99):该方法适用于非平面相机标定,需要标定板放置在不同的位置和角度,通过解方程组来求解相机内部参数和外部参数。
HarrisCorner(Harris角检测)
HarrisCorner(Harris⾓检测)在做图像匹配时,常需要对两幅图像中的特征点进⾏匹配。
为了保证匹配的准确性,所选择的特征必须有其独特性,⾓点可以作为⼀种不错的特征。
那么为什么⾓点有其独特性呢?⾓点往往是两条边缘的交点,它是两条边缘⽅向变换的⼀种表⽰,因此其两个⽅向的梯度变换通常都⽐较⼤并且容易检测到。
这⾥我们理解⼀下Harris Corner ⼀种⾓点检测的算法⾓点检测基本原理:⼈们通常通过在⼀个⼩的窗⼝区域内观察点的灰度值⼤⼩来识别⾓点,如果往任何⽅向移动窗⼝都会引起⽐较⼤的灰度变换那么往往这就是我们要找的⾓点。
如下图右下⾯我们看⼀下Harris的数学公式,对于[x,y]平移[u,v]个单位后强度的变换有下式,I(x+u,y+v)是平移后的强度,I(x,y)是原图像像素。
对于括号⾥⾯的值,如果是强度恒定的区域,那么它就接近于零,反之如果强度变化剧烈那么其值将⾮常⼤,所以我们期望E(u,v)很⼤。
其中w是窗函数,它可以是加权函数,也可以是⾼斯函数利⽤⼆维泰勒展开式我们有所以其中⼀阶可以近似为于是我们可以给出Harris Corner的如下推导,其中Ix,Iy是x,y⽅向的Gradient模,乘以位移得到位移后的量对于⼩的位移,我们可以⽤双线性插值⽅法近似:其中M为2*2矩阵如下在本质上我们可以把⼆次项看成⼀个椭圆函数,我们对M进⾏特征值分析有λ1,λ2根据λ1,λ2的值我们可以把其分为三类:1.λ1,λ2都很⼩且近似,E在所以⽅向接近于常数;2.λ1>>λ2,或者λ2>>λ1, E将在某⼀⽅向上很⼤;3.λ1,λ2都很⼤且近似,E将在所以⽅向上很⼤;如图所⽰:最后我们通过计算⾓点响应值R来判断其属于哪个区间其中k⼀般为常数取在0.04-0.06间。
算法步骤:1.计算图像x,y⽅向的梯度I x,I y2.计算每个像素点的梯度平⽅3.计算梯度在每个像素点的和4.定义在每个像素点的矩阵H,也就是前⾯的M5.计算每个像素的⾓点响应6.设置阈值找出可能点并进⾏⾮极⼤值抑制代码:close allclear allI = imread('empire.jpg');I = rgb2gray(I);I = imresize(I,[500,300]);imshow(I);sigma = 1;halfwid = sigma * 3;[xx, yy] = meshgrid(-halfwid:halfwid, -halfwid:halfwid);Gxy = exp(-(xx .^ 2 + yy .^ 2) / (2 * sigma ^ 2));Gx = xx .* exp(-(xx .^ 2 + yy .^ 2) / (2 * sigma ^ 2));Gy = yy .* exp(-(xx .^ 2 + yy .^ 2) / (2 * sigma ^ 2));%%apply sobel in herizontal direction and vertical direction compute the %%gradient%fx = [-1 0 1;-1 0 1;-1 0 1];%fy = [1 1 1;0 0 0;-1 -1 -1];Ix = conv2(I,Gx,'same');Iy = conv2(I,Gy,'same');%%compute Ix2, Iy2,IxyIx2 = Ix.*Ix;Iy2 = Iy.*Iy;Ixy = Ix.*Iy;%%apply gaussian filterh = fspecial('gaussian',[6,6],1);Ix2 = conv2(Ix2,h,'same');Iy2 = conv2(Iy2,h,'same');Ixy = conv2(Ixy,h,'same');height = size(I,1);width = size(I,2);result = zeros(height,width);R = zeros(height,width);Rmax = 0;%% compute M matrix and corner responsefor i = 1:heightfor j =1:widthM = [Ix2(i,j) Ixy(i,j);Ixy(i,j) Iy(i,j)];R(i,j) = det(M) - 0.04*(trace(M)^2);if R(i,j)> RmaxRmax = R(i,j);endendend%% compare whith thresholdcount = 0;for i = 2:height-1for j = 2:width-1if R(i,j) > 0.01*Rmaxresult(i,j) = 1;count = count +1;endendend%non-maxima suppressionresult = imdilate(result, [1 1 1; 1 0 1; 1 1 1]); [posc,posr] = find(result == 1);imshow(I);hold on;plot(posr,posc,'r.');本⽂原创,转载请注明出处。
视觉系统实验报告(3篇)
第1篇一、实验目的通过本次实验,我们旨在了解和掌握视觉系统的基本原理和常用算法,学习如何使用Python和OpenCV库实现图像处理和特征提取,并对实验结果进行分析和评估。
实验内容主要包括图像预处理、边缘检测、特征点检测和目标识别等。
二、实验原理1. 图像预处理图像预处理是图像处理的基础,主要包括图像灰度化、二值化、滤波、锐化等操作。
通过预处理,可以提高图像质量,为后续处理提供更好的数据基础。
2. 边缘检测边缘检测是图像处理中的重要步骤,主要用于提取图像中的边缘信息。
常用的边缘检测算法有Sobel算子、Prewitt算子、Laplacian算子等。
3. 特征点检测特征点检测是图像识别的关键,常用的特征点检测算法有Harris角点检测、SIFT算法、SURF算法等。
4. 目标识别目标识别是计算机视觉中的高级应用,通过提取图像特征,建立特征模型,实现对目标的识别。
常用的目标识别算法有支持向量机(SVM)、神经网络(NN)等。
三、实验内容1. 图像预处理(1)读取实验图像使用OpenCV库读取实验图像,并进行灰度化处理。
(2)二值化处理对灰度图像进行二值化处理,提取图像中的前景和背景。
(3)滤波处理使用高斯滤波器对图像进行滤波,去除噪声。
2. 边缘检测(1)Sobel算子边缘检测使用Sobel算子对图像进行边缘检测,提取图像中的边缘信息。
(2)Prewitt算子边缘检测使用Prewitt算子对图像进行边缘检测,提取图像中的边缘信息。
3. 特征点检测(1)Harris角点检测使用Harris角点检测算法,提取图像中的角点特征。
(2)SIFT算法特征点检测使用SIFT算法,提取图像中的特征点。
4. 目标识别(1)特征提取使用提取到的特征点,建立特征模型。
(2)目标识别使用支持向量机(SVM)对目标进行识别。
四、实验步骤1. 导入实验图像使用OpenCV库导入实验图像。
2. 图像预处理对图像进行灰度化、二值化、滤波处理。
c++ 角点算法
角点算法通常用于图像处理中来检测和识别图像中的角点。
下面是一个简单的C++示例代码,演示如何使用OpenCV库来实现角点检测。
cpp复制代码
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
int main() {
// 读取图像
Mat image = imread("image.jpg");
// 创建Harris角点检测器
Ptr<Detector> detector = createHarrisDetector(3, 3, 0.04, 100.0, 50);
// 检测角点
vector<Point2f> corners;
detector->detect(image, corners);
// 在图像上绘制角点
for (int i = 0; i < corners.size().size(); i++) {
circle(image, corners[i], 5, Scalar(0, 255, 0), -1);
}
// 显示结果
imshow("Harris Corner Detection", image);
waitKey(0);
return0;
}
在上述代码中,我们首先使用OpenCV库读取一张图像。
然后,我们创建一个Harris角点检测器,并使用该检测器来检测图像中的角点。
最后,我们在图像上绘制检测到的角点,并显示结果。
harris角点检测原理步骤说明[技巧]
一、Harris角点检测基本理论1.1 简略表达:角点:最直观的印象就是在水平、竖直两个方向上变化均较大的点,即Ix、Iy都较大边缘:仅在水平、或者仅在竖直方向有较大的变化量,即Ix和Iy只有其一较大平坦地区:在水平、竖直方向的变化量均较小,即Ix、Iy都较小角点响应R=det(M)-k*(trace(M)^2) (附录资料给出k=0.04~0.06,opencv指出是0.05-0.5,浮动较大)det(M)=λ1*λ2trace(M)=λ1+λ2R取决于M的特征值,对于角点|R|很大,平坦的区域|R|很小,边缘的R为负值。
1.2 详细描述:见附录里的ppt1.3 算法步骤其中,局部极大值可用先膨胀后与原图比较的方法求得,具体见二中源码。
二、opencv代码实现harris类[cpp]view plaincopyprint?1. #ifndef HARRIS_H2. #define HARRIS_H3. #include "opencv2/opencv.hpp"4.5. class harris6. {7. private:8. cv::Mat cornerStrength; //opencv harris函数检测结果,也就是每个像素的角点响应函数值9. cv::Mat cornerTh; //cornerStrength阈值化的结果10. cv::Mat localMax; //局部最大值结果11. int neighbourhood; //邻域窗口大小12. int aperture;//sobel边缘检测窗口大小(sobel获取各像素点x,y方向的灰度导数)13. double k;14. double maxStrength;//角点响应函数最大值15. double threshold;//阈值除去响应小的值16. int nonMaxSize;//这里采用默认的3,就是最大值抑制的邻域窗口大小17. cv::Mat kernel;//最大值抑制的核,这里也就是膨胀用到的核18. public:19. harris():neighbourhood(3),aperture(3),k(0.01),maxStrength(0.0),threshold(0.01),nonMaxSize(3){20.21. };22.23. void setLocalMaxWindowsize(int nonMaxSize){24. this->nonMaxSize = nonMaxSize;25. };26.27. //计算角点响应函数以及非最大值抑制28. void detect(const cv::Mat &image){29. //opencv自带的角点响应函数计算函数30. cv::cornerHarris (image,cornerStrength,neighbourhood,aperture,k);31. double minStrength;32. //计算最大最小响应值33. cv::minMaxLoc (cornerStrength,&minStrength,&maxStrength);34.35. cv::Mat dilated;36. //默认3*3核膨胀,膨胀之后,除了局部最大值点和原来相同,其它非局部最大值点被37. //3*3邻域内的最大值点取代38. cv::dilate (cornerStrength,dilated,cv::Mat());39. //与原图相比,只剩下和原图值相同的点,这些点都是局部最大值点,保存到localMax40. cv::compare(cornerStrength,dilated,localMax,cv::CMP_EQ);41. }42.43. //获取角点图44. cv::Mat getCornerMap(double qualityLevel) {45. cv::Mat cornerMap;46. // 根据角点响应最大值计算阈值47. threshold= qualityLevel*maxStrength;48. cv::threshold(cornerStrength,cornerTh,49. threshold,255,cv::THRESH_BINARY);50. // 转为8-bit图51. cornerTh.convertT o(cornerMap,CV_8U);52. // 和局部最大值图与,剩下角点局部最大值图,即:完成非最大值抑制53. cv::bitwise_and(cornerMap,localMax,cornerMap);54. return cornerMap;55. }56.57. void getCorners(std::vector<cv::Point> &points,58. double qualityLevel) {59. //获取角点图60. cv::Mat cornerMap= getCornerMap(qualityLevel);61. // 获取角点62. getCorners(points, cornerMap);63. }64.65. // 遍历全图,获得角点66. void getCorners(std::vector<cv::Point> &points,67. const cv::Mat& cornerMap) {68.69. for( int y = 0; y < cornerMap.rows; y++ ) {70. const uchar* rowPtr = cornerMap.ptr<uchar>(y);71. for( int x = 0; x < cornerMap.cols; x++ ) {72. // 非零点就是角点73. if (rowPtr[x]) {74. points.push_back(cv::Point(x,y));75. }76. }77. }78. }79.80. //用圈圈标记角点81. void drawOnImage(cv::Mat &image,82. const std::vector<cv::Point> &points,83. cv::Scalar color= cv::Scalar(255,255,255),84. int radius=3, int thickness=2) {85. std::vector<cv::Point>::const_iterator it=points.begin();86. while (it!=points.end()) {87. // 角点处画圈88. cv::circle(image,*it,radius,color,thickness);89. ++it;90. }91. }92.93. };94.95. #endif // HARRIS_H相关测试代码:[cpp]view plaincopyprint?1. cv::Mat image, image1 = cv::imread ("test.jpg");2. //灰度变换3. cv::cvtColor (image1,image,CV_BGR2GRAY);4.5.6. // 经典的harris角点方法7. harris Harris;8. // 计算角点9. Harris.detect(image);10. //获得角点11. std::vector<cv::Point> pts;12. Harris.getCorners(pts,0.01);13. // 标记角点14. Harris.drawOnImage(image,pts);15.16. cv::namedWindow ("harris");17. cv::imshow ("harris",image);18. cv::waitKey (0);19. return 0;相关测试结果:三、改进的Harris角点检测从经典的Harris角点检测方法不难看出,该算法的稳定性和k有关,而k是个经验值,不好把握,浮动也有可能较大。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
随着计算机技术的不断发展 , 计算机视觉已成为计算机领域中的热门研究课题之一. 利用相机采集图像 再结合图像处理和机器视觉等基础知识进行几何体相关参数视觉测量的技术 , 已经在现实生活中得到广泛
方 向发生 小小 的偏 移都 能 引起灰 度 的较 大变 化 , 么就认 为该 点是 角点 . 那
哈里斯检测算法受信号处理中 自 相关函数的启发认为 , 对于一 幅图片 , 角点与 自 相关 函数的曲率特性
相关 , 自相关 函数 表述 了局部 图像 灰度 的变 化程 度 , 并把 灰度 变化 度量 定义 为 :
的应用. 在进行视觉测量工作之前 , 首先要对摄像头进行标定 , 因为相机标定精度在很大程度上决定了视觉
测量的精度. 标定就是要计算出摄像头 的标定 内外参数以及 畸变参数 , 』其结果可以找出世界坐标 和图像 坐标之间的变换关系 , 所以寻找标定点的图像坐标是相机标定的重要环节. 由于角点包含了被识别物重要的 几何参数信息, 而在相机标定中需要利用到黑白棋盘格图片 , 以利用角点检测获取检测黑 白棋盘格图像中 所 的角点 , 从而可以获取特征点的像素坐标 . , 为相机参数标定提供 了已知条件. 在计算机视觉领域 中, 角点检测技术可以大致分为两大类 : 一类是基于图像边缘信息如基于边界链码和
小波变换模的角点检测算法 ; 另一类是基于图像灰度信息如 H rs 哈里斯 ) ai r( 算法 的角点检测技术. 第一
类算法在角点检测时较多依赖于边缘线 , 假设 由于某种原 因边缘线发生 中断, 则会对角点的检测及提取结果
产生 影 响. 比如 , 当镜 头为 广角 镜 时 ,会产 生 比较 大 的 畸变 ,边 缘检 测 后 棋 盘格 的边缘 会 发 生 弯 曲 , 时 的 这
化. 哈里斯 的角 点响应 函数 ( R H F)可 以表示 为 :
职 F( y =d tM)一k t c ( , , ) e( (r e M) ) a () 6
E
,
=
∑W, )+2 y + u J= x+ CY B u ( v , 2 v L () A 2 + y,
() 2
式中, = ( ) A o C = ( ・y W, I)O B : ( o ( 表示卷 积 ) W, L) W o .
计算 E 的二次型得 :
H ri ar s算法的基 本原理 , O e C 在 pn V算法环境 下运 用 Ha i 算法对 黑白棋盘格 图像进行 角点检测 , rs r 实验结果可以应用在摄像机
的标定 当中, 具有一定的应用价值.
关键词 : 角点 ; r s Ha i 算法 ; r 角点检 测 ; pn V O eC
1 H ns a i角点检测算 法的基本原理
角点被定义为图像边缘曲线上曲率极大值的点或图像亮度变化剧烈的点 , 这些点既保 留了图像的重要 特征 , 又有效地减少了信息 的数据量. a i算法 以 M r e H rs r o v 算法为基础 , a J其检测原理为 : 如果某一点朝任
一
第2 3卷 第 4期
21 0 1年 l 2月
河 南工程 学院学报( 自然科学版)
J URNAL 0F HE O NAN NS I UT GI ER NG I T T E OF EN NE I
V0. 3. o 4 12 N . De . 0 1 c 2 1
基 于 Op n V 的 H rs角 点 检 测 eC ar i
收稿 日期 :0 1 0—2) 2 1 一l I
。 对于任何微小的偏移 , 略去无穷小项得 :
作者简介 : 陈凯歌(95 , 河 南平顶 山人 ,i: " , 18 一) 男, 3t ,-N究生 主要从事 图 处理与模 式识别方面的研 究 , 像
・
5 4・
河 南工程学院学报(自然科 学版)
陈凯歌 韩 晓军 张 宇 , , , 杜云飞
(. 1 天津工业大学 电子与信息工程 学院 , 天津 30 8 ;. 0 372 天津工业大学 理学院 , 天津 30 8 ) 03 7
摘 要: 角点检测在运动估计 、 光流计算 、 觉定位、 D重建和相机标定 、 视 3 形状测量和分析等方 面都有广泛的应用. 详述 了
检测结果就会产生较大误差. a i角点检测是 目前效果较好的角点检测算法 , H rs r 它不仅不受摄像机姿态以及 光照的影响 ]而且还适用于数 目较多的: , 自点且光源复杂的情况 , 同时还具有计算简单、 提取方便 、 稳定等 诸多优点. 鉴于以上情况 , 本文采用 H rs a i检测算法对黑 白棋盘格图像进行角点检测. r
E :∑加 I
一 I , =∑加 I
+ + ( 2 +J l, yl 0, ̄ t) O / u
() 1
式中 ,… 为窗 口偏移 ( ,) E , 所引起的图像灰度的平均变化度量 ;代表图像灰度 函数 , , J 『 W为窗 口函数 , ,为 U 滤波窗的系数 , 通常情况下 加 =e
E =u川 . , 1 v
为实 对称矩 阵 :
( 3 )
M ∑ [ . = 驯. I
x
㈩
对 式 ( ) 行对 角化处 理得 : 4 进
% (
㈣
式 中, R为旋转因子 , 对角化处理后并不改变 以 为坐标参数的空间曲面的形状 , , 其特征值反映了2 个主轴 方向的图像表面曲率. 如果 2个特征值都较小 , 那么表明特征点周围区域为“ 平坦区域” 若特征值为一大一 ; 小, 那表明目标点位于“ 边缘”上; 当且仅当 2 个特征值都较大时 , 沿任何方向的偏移都将导致剧烈的灰度变