1. 直线检测

1.1. Radon直线检测原理

基于Radon变换的直线检测的目的就是检测根据角度变化时出现的“局部峰值”,即可以确定直线的方向,同时,峰值大小能够确定直线上点的个数

1.2. Hough 直线检测原理

将直线利用极坐标表示时,一条直线即可通过角度和长度确定,通过对角度和长度计算累计图,寻找峰值点即可确定一条直线:

1.3. 正弦图合击-分进直线检测

2. 实现代码

%LineDetection.m
%Author: HSW
%Date: 2015/4/21
%HARBIN INSTITUTE OF TECHNOLOGY
%
%Set Matlab
close all;
clear all;
clc;
% Add Path
addpath(genpath('MultiLayerLineUtil\'));
addpath(genpath('SingleLayerLineUtil\'));
addpath(genpath('RadonLineUtil\'));
% 测试图像路径和结果保存路径
ImageFilePath = 'TestImage\';
SaveFilePath = 'Results\';
type = ['*.png';'*.bmp';'*.jpg'];
MaxSigma = 1;
sigmastep = 0.05;
% 考虑是否需要设置Neighborstep 和 MaxNeighbor,因为每张图都不一样
% ,特别是随着噪声的增大时,Neighbor需要增大可能更好
Neighborstep = 5;
MaxNeighbor = 60;
Neighbor = 11;%比较算法如下
%1. 标准Hough变换直线检测
%2. 标准Radon变换直线检测
%3. 基于Fourier变换的Radon变换直线检测
%4. 基于MultiLayer Fourier变换的Radon变换直线检测
%5. 零填充Fourier变换的Radon变换直线检测(扩大图像)% imgdir = dir(fullfile(ImageFilePath,type(1,:))); %修改为type(2,:)
% 处理.bmp格式图片, type(3,:),处理.jpg格式图片,这里是为了批处理(但是这里不需要)
% for iterimage = 1:length(imgdir)
% Img = imread(fullfile(ImageFilePath,imgdir(iterimage).name));
% Img = imread(fullfile(ImageFilePath,'NewLine2.png'));Nhood = [51,51];   Numpeaks = 1; %注意修改peaks的数目
% Img = imread(fullfile(ImageFilePath,'NewOneLine.png'));Nhood = [51,51];   Numpeaks = 1; %注意修改peaks的数目
% Img = imread(fullfile(ImageFilePath,'OneLine1.png'));Nhood = [51,51];   Numpeaks = 1; %注意修改peaks的数目
% Img = imread(fullfile(ImageFilePath,'OneLine.png'));Nhood = [51,51];   Numpeaks = 1; %注意修改peaks的数目
% Img = imread(fullfile(ImageFilePath,'Line30_256.png')); Nhood = [31,31];   Numpeaks = 30; %注意修改peaks的数目
Img = imread(fullfile(ImageFilePath,'Line30_512.png')); Nhood = [31,31];   Numpeaks = 31; %注意修改peaks的数目
% Img = 255-imread(fullfile(ImageFilePath,'house.png'));Nhood = [51,51];   Numpeaks = 11; %注意修改peaks的数目
% Img = imread(fullfile(ImageFilePath,'half.png'));Nhood = [51,51];   Numpeaks = 1; %注意修改peaks的数目
% Img = imread(fullfile(ImageFilePath,'paper.png'));Nhood = [11,11];   Numpeaks = 3; %注意修改peaks的数目
% Img = imread(fullfile(ImageFilePath,'5line.png'));Nhood = [31,31];   Numpeaks = 5; %注意修改peaks的数目
if size(Img,3) == 3Img = rgb2gray(Img);
end
NextPow1 = nextpow2(size(Img,1));
NextPow2 = nextpow2(size(Img,2));
if abs(size(Img,1) - 2^NextPow1) > abs(size(Img,1) - 2^(NextPow1 - 1))NextPow1 = NextPow1 -1;
end
if abs(size(Img,2) - 2^NextPow2) > abs(size(Img,2) - 2^(NextPow2 - 1))NextPow2 = NextPow2 - 1;
end
NextPow = max(NextPow1,NextPow2);
Img = imresize(Img,[2^NextPow, 2^NextPow],'bicubic');for itersigma = 1:MaxSigmanImg = double(Img) + (itersigma - 1)*randn(size(Img)); %添加噪声% 标准Hough变换直线检测EdImg = edge(nImg,'canny');%     title('待检测图像');[R,theta,rho] = hough(EdImg,'ThetaResolution',1);% 峰值个数%检测的峰值为2xNumpeaks的数组, rho = peaks(:,2), theta = peaks(:,1)peaks = houghpeaks(R,Numpeaks,'Threshold',0.1*max(R(:)),'Nhood',Nhood);%显示检测到的峰值if ~isempty(peaks)figure;%         subplot(1,3,2);imshow(R,[]);title('正弦图像');for iter = 1:size(peaks,1)hold on;scatter(peaks(iter,2),peaks(iter,1),'r');endendlines = houghlines(EdImg,theta,rho,peaks,'FillGap',5,'MinLength',7);if ~isempty(lines)figure;imshow(nImg/255,[]);hold on;title('Hough变换');for iter = 1:length(lines)            xy = [lines(iter).point1;lines(iter).point2];plot(xy(:,1),xy(:,2),'LineWidth',1,'Color','green');endend% 标准Radon变换直线检测EdImg = edge(nImg,'sobel');% 角分辨率theta = 0:0.5:179.5;%进行Radon变换[R,rho] = radon(EdImg,theta);%检测的峰值为2xNumpeaks的数组, rho = peaks(:,2), theta = peaks(:,1)peaks = radonpeaks(R,Numpeaks,'Threshold',0,'Nhood',Nhood);%显示检测到的峰值if ~isempty(peaks)figure; imshow(R,[]);title('正弦图');for iter = 1:size(peaks)hold on;scatter(peaks(iter,2),peaks(iter,1),'r');endend% 显示检测到的直线type = 1;if type == 1radonlines(nImg,theta,rho',peaks,type);elseif type == 2lines = radonlines(EdImg,theta,rho',peaks,type,20,40,2);if ~isempty(lines)figure;imshow(nImg);title('Radon变换');for iter = 1:length(lines)hold on;xy = [lines(iter).point1;lines(iter).point2];plot(xy(:,1),xy(:,2),'LineWidth',1,'Color','green');endendend%基于Fourier变换的Radon变换直线检测shiftImg = fftshift(nImg);fftImg = FractionalFT(shiftImg,1,1); % 进行fourier变换Center = round(0.5*size(fftImg)); %中心坐标gridfftImg = [(-0.5*size(fftImg,1):0.5*size(fftImg,1)-1)',(-0.5*size(fftImg,2):0.5*size(fftImg,2)-1)'];MaxRho = sqrt(sum(sum((0.5*size(fftImg)).^2)));Nrho = round(MaxRho);Ntheta = length(0:0.5:179.5);de=59;di=26;ax = [1,1,1];ay = ax;fftImg = xvMappingOpt(gridfftImg,gridfftImg,gridfftImg,fftImg,fftImg,fftImg,Nrho,Ntheta+1,ax,ay,de,di,Center(1),Center(2));fftImg = fftImg(1:Nrho,1:Ntheta);conjfftImg = flipud(conj(fftImg));TwofftImg = [conjfftImg;fftImg(2:end,:)];radonImg = fft(TwofftImg);radonImg = abs(radonImg)/size(fftImg,1);L1 = radonImg(1:size(fftImg,1),:);L2 = radonImg(size(fftImg,1)+1:2*size(fftImg,1)-1,:);Ra = flipud([L2;L1]);
%     NormalRa = abs(Ra)/max(max(abs(Ra)));%     % 峰值个数%     Numpeaks = 3;%检测的峰值为2xNumpeaks的数组, rho = peaks(:,2), theta = peaks(:,1)peaks = radonpeaks(abs(Ra)*10000,Numpeaks,'Threshold',0.1*10000*ceil(max(max(abs(Ra)))),'Nhood',Nhood);%显示检测到的峰值if ~isempty(peaks)figure;imshow(log(abs(Ra) + 1),[]);for iter = 1:size(peaks,1)hold on;scatter(peaks(iter,2),peaks(iter,1),'r');endend% 显示检测到的直线[h,w,ncolor]=size(nImg);r=0.5*sqrt(2)*w;Factor = Nrho/size(Img,1);centery=floor(h*0.5)+1;centerx=floor(w*0.5)+1;r=0.5*sqrt(2)*w;figure;imshow(nImg/255,[]);title('Single-Layer Fourier'); hold on;for count=1:size(peaks,1)r1a=peaks(count,1);%rhoc1=peaks(count,2); %thetarho1=Factor*(r1a-Nrho-1)/Nrho*r;%为什么要乘以0.5?theta1=(c1-1)/Ntheta*180;if rho1 <= 0 && theta1 <= 90 % 直线在左下角theta2 = 90-theta1;slope = tan((theta2)*pi/180);y1 = centery - rho1*sin(theta1*pi/180);x1 = centerx + rho1*cos(theta1*pi/180);elseif rho1 < 0 && theta1 > 90% 直线在右下角theta2 = 270-theta1;theta1 = 180-theta1;slope = tan((theta2)*pi/180);y1 = centery - rho1*sin(theta1*pi/180);x1 = centerx - rho1*cos(theta1*pi/180);elseif rho1 > 0 && theta1 < 90 % 直线在右上角theta2 = 90 - theta1;slope = tan((theta2)*pi/180);y1 = centery - rho1*sin(theta1*pi/180);x1 = centerx + rho1*cos(theta1*pi/180);else% 直线在左上角theta2 = 270-theta1;theta1 = 180-theta1;slope = tan((theta2)*pi/180);y1 = centery - rho1*sin(theta1*pi/180);x1 = centerx - rho1*cos(theta1*pi/180);end x =centerx-size(Img,2):centerx+size(Img,2);y = slope*(x-x1) + y1;plot(x,y,'g')end% 多层fourier变换直线检测ax=[];ay=[];I1=double(nImg);I1=fftshift(I1);[h,w]=size(I1);x0=-w*0.5:w*0.5-1;y0=-h*0.5:h*0.5-1;centery=floor(h*0.5)+1;centerx=floor(w*0.5)+1;a1=0.8;a2=0.9;x1=a1*x0;y1=a2*y0;ax=[ax a1];ay=[ay a2];f1=FractionalFT(I1,a1,a2);a1=0.9;a2=0.7;x2=x0*a1;y2=y0*a2;ax=[ax a1];ay=[ay a2];f2=FractionalFT(I1,a1,a2);a1=1;a2=1;x3=x0*a1;y3=y0*a2;ax=[ax a1];ay=[ay a2];f3=FractionalFT(I1,a1,a2);%creat gridgrid1=[x1' y1'];grid2=[x2' y2'];grid3=[x3' y3'];%computer the covariancetheta=Ntheta;rho=Nrho;de=59;di=26;%thL=0.5*dr; thH=10*dr;%0.8*sigma;L1=xvMappingOpt(grid1,grid2,grid3,f1,f2,f3,rho,theta+1,ax,ay,de,di,centery,centerx);L1=L1(1:rho,1:theta);L2=flipud(conj(L1));%L3=cat(1,L2,L1);L3=[L2;L1(2:rho,:)];%忽略重复的0度,并且相当于求了共轭% %perform 1D FFT for each columnYfreqDomain=fft(L3);L=abs(YfreqDomain)/h;L1=L(1:rho,:);L2=L(rho+1:rho*2-1,:);Ra=flipud([L2L1]);NormalRa=abs(Ra)/max(max(abs(Ra)));%Peak DetectionH = log(abs(Ra)+1)*10000;peaks=radonpeaks(H,Numpeaks,'threshold',ceil(0.0001*max(H(:))),'Nhood',Nhood);%显示检测到的峰值if ~isempty(peaks)figure;imshow(log(abs(Ra) + 1),[]);for iter = 1:size(peaks,1)hold on;scatter(peaks(iter,2),peaks(iter,1),'r');endendfigure; imshow(nImg/255,[]);title('Multi-Layer Fourier'); hold on; for count=1:size(peaks,1)r1a=peaks(count,1);%rhoc1=peaks(count,2); %thetarho1=Factor*(r1a-Nrho-1)/Nrho*r;%为什么要乘以0.5?theta1=(c1-1)/Ntheta*180;if rho1 <= 0 && theta1 <= 90 % 直线在左下角theta2 = 90-theta1;slope = tan((theta2)*pi/180);y1 = centery - rho1*sin(theta1*pi/180);x1 = centerx + rho1*cos(theta1*pi/180);elseif rho1 < 0 && theta1 > 90% 直线在右下角theta2 = 270-theta1;theta1 = 180-theta1;slope = tan((theta2)*pi/180);y1 = centery - rho1*sin(theta1*pi/180);x1 = centerx - rho1*cos(theta1*pi/180);elseif rho1 > 0 && theta1 < 90 % 直线在右上角theta2 = 90 - theta1;slope = tan((theta2)*pi/180);y1 = centery - rho1*sin(theta1*pi/180);x1 = centerx + rho1*cos(theta1*pi/180);else% 直线在左上角theta2 = 270-theta1;theta1 = 180-theta1;slope = tan((theta2)*pi/180);y1 = centery - rho1*sin(theta1*pi/180);x1 = centerx - rho1*cos(theta1*pi/180);end x =centerx-size(Img,2):centerx+size(Img,2);y = slope*(x-x1) + y1;plot(x,y,'g')end %for itersigma
end
% end%for iterimage% % 读入图像
% % 实验1 peaks = houghpeaks(R,Numpeaks,'Nhood',[51,51]);
% Img = imread('paper.png');
%
% % 实验2 peaks = houghpeaks(R,Numpeaks,'Nhood',[51,51]);
% % Img = imread('ThreeLine.bmp');
% % Img = 255 - Img;
%
% % 实验3 peaks = houghpeaks(R,Numpeaks,'Nhood',[11,11]);
% % Img = imread('SevenLine.png');
% if size(Img,3) == 3
%     Img = rgb2gray(Img);
% end

Radon变换直线检测代码:

function lines = radonlines(varargin)
%RADONLINES Extract line segments based on Radon transform.
%
%   LINES = HOUGHLINES(...,PARAM1,VAL1,PARAM2,VAL2) sets various
%   parameters. Parameter names can be abbreviated, and case
%   does not matter. Each string parameter is followed by a value
%   as indicated below:
%
%   'FillGap'   Positive real scalar.
%               When HOUGHLINES finds two line segments associated
%               with the same Hough transform bin that are separated
%               by less than 'FillGap' distance, HOUGHLINES merges
%               them into a single line segment.
%
%               Default: 20 直线进行合并
%
%   'MinLength' Positive real scalar.
%               Merged line segments shorter than 'MinLength'
%               are discarded.
%
%               Default: 40 直线的最短长度
%
%   Class Support
%   -------------
%   BW can be logical or numeric and it must be real, 2-D, and nonsparse.
% Author: HSW
% Date: 2015/4/21
% HARBIN INSTITUTE OF TECHNOLOGY
%
center = floor((0.5*size(varargin{1})));
centery = center(1);
centerx = center(2);
theta = varargin{2};
rho = varargin{3};
peaks = varargin{4};
type = varargin{5}; % 选择画直线还是画线段
if isempty(peaks)disp('no peaks');return;
endif type == 1% 画直线figure;imshow(varargin{1});hold on;for iter = 1:size(peaks,1)rho1 = rho(peaks(iter,1));theta1 = theta(peaks(iter,2));if rho1 <= 0 && theta1 <= 90% 直线在左下角theta2 = 90-theta1;slope = tan((theta2)*pi/180);y1 = centery - rho1*sin(theta1*pi/180);x1 = centerx + rho1*cos(theta1*pi/180);elseif rho1 < 0 && theta1 > 90% 直线在右下角theta2 = 270-theta1;theta1 = 180-theta1;slope = tan((theta2)*pi/180);y1 = centery - rho1*sin(theta1*pi/180);x1 = centerx - rho1*cos(theta1*pi/180);elseif rho1 > 0 && theta1 < 90% 直线在右上角theta2 = 90 - theta1;slope = tan((theta2)*pi/180);y1 = centery - rho1*sin(theta1*pi/180);x1 = centerx + rho1*cos(theta1*pi/180);else% 直线在左上角theta2 = 270-theta1;theta1 = 180-theta1;slope = tan((theta2)*pi/180);y1 = centery - rho1*sin(theta1*pi/180);x1 = centerx - rho1*cos(theta1*pi/180);endx =centerx-size(varargin{1},2):centerx+size(varargin{1},2);y = slope*(x-x1) + y1;plot(x,y,'g')end
elseif type == 2% 画线段fillgap = varargin{6};minlength = varargin{7};delta = varargin{8};minlength_sq = minlength^2;fillgap_sq = fillgap^2;numlines = 0;[y,x] = find(varargin{1});nonzeropix = [x,y] - 1;lines = struct([]);for k = 1:size(peaks,1)[r,c] = radonpixels(nonzeropix,theta,rho,delta,peaks(k,:),center);if isempty(r)continue;end% Compute distance^2 between the point pairsxy = [c r]; % x,y pairs in coordinate system with the origin at (1,1)diff_xy_sq = diff(xy,1,1).^2;dist_sq = sum(diff_xy_sq,2);% Find the gaps larger than the thresholdfillgap_idx = find(dist_sq > fillgap_sq);idx = [0; fillgap_idx; size(xy,1)];for p = 1:length(idx) - 1p1 = xy(idx(p) + 1,:); % offset by 1 to convert to 1 based indexp2 = xy(idx(p + 1),:); % set the end (don't offset by one this time)linelength_sq = sum((p2-p1).^2);if linelength_sq >= minlength_sqnumlines = numlines + 1;lines(numlines).point1 = p1;lines(numlines).point2 = p2;lines(numlines).theta = theta(peaks(k,2));lines(numlines).rho = rho(peaks(k,1));endendend %for k = 1:size(peaks,1)
elseerror('type = 1 or type = 2');
end %if typeend %function radonlinesfunction [r,c] = radonpixels(nonzeropix,theta,rho,delta,peak,center)
x = nonzeropix(:,1);
y = nonzeropix(:,2);
centery = center(1);
centerx = center(2);
rho1 = rho(peak(1));
theta1 = theta(peak(2));
if rho1 <= 0 && theta1 <= 90% 直线在左下角theta2 = 90-theta1;slope = tan((theta2)*pi/180);y1 = centery - rho1*sin(theta1*pi/180);x1 = centerx + rho1*cos(theta1*pi/180);
elseif rho1 < 0 && theta1 > 90% 直线在右下角theta2 = 270-theta1;theta1 = 180-theta1;slope = tan((theta2)*pi/180);y1 = centery - rho1*sin(theta1*pi/180);x1 = centerx - rho1*cos(theta1*pi/180);
elseif rho1 > 0 && theta1 < 90% 直线在右上角theta2 = 90 - theta1;slope = tan((theta2)*pi/180);y1 = centery - rho1*sin(theta1*pi/180);x1 = centerx + rho1*cos(theta1*pi/180);
else% 直线在左上角theta2 = 270-theta1;theta1 = 180-theta1;slope = tan((theta2)*pi/180);y1 = centery - rho1*sin(theta1*pi/180);x1 = centerx - rho1*cos(theta1*pi/180);
end
idx = find(abs(slope*(x-x1) + y1 - y) <= delta); %进行直线拟合
r = y(idx) + 1;
c = x(idx) + 1;
[r,c] = reSortRadonPixels(r,c);
end% function radonpixelsfunction [r_new,c_new] = reSortRadonPixels(r,c)if isempty(r)r_new = r;c_new = c;return;
endr_range = max(r) - min(r);
c_range = max(c) - min(c);if r_range > c_rangesorting_order = [1,2];
elsesorting_order = [2,1];
end
[rc_new] = sortrows([r,c],sorting_order);
r_new = rc_new(:,1);
c_new = rc_new(:,2);
end % function reSortRadonPixels
function peaks = radonpeaks(varargin)
% RADONPEAKS Identify peaks in Radon transform.
%   PEAKS = HOUGHPEAKS(H,NUMPEAKS) locates peaks in the Hough
%   transform matrix, H, generated by the HOUGH function. NUMPEAKS
%   specifies the maximum number of peaks to identify. PEAKS is
%   a Q-by-2 matrix, where Q can range from 0 to NUMPEAKS. Q holds
%   the row and column coordinates of the peaks. If NUMPEAKS is
%   omitted, it defaults to 1.
%
%   PEAKS = HOUGHPEAKS(...,PARAM1,VAL1,PARAM2,VAL2) sets various
%   parameters. Parameter names can be abbreviated, and case
%   does not matter. Each string parameter is followed by a value
%   as indicated below:
%
%   'Threshold' Nonnegative scalar.
%               Values of H below 'Threshold' will not be considered
%               to be peaks. Threshold can vary from 0 to Inf.
%
%               Default: 0.5*max(H(:))
%
%   'NHoodSize' Two-element vector of positive odd integers: [M N].% odd 奇数
%               'NHoodSize' specifies the size of the suppression
%               neighborhood. This is the neighborhood around each
%               peak that is set to zero after the peak is identified.
%
%               Default: smallest odd values greater than or equal to
%                        size(H)/50.
%
%   Class Support
%   -------------
%   H is the output of the HOUGH function. NUMPEAKS is a positive
%   integer scalar.
%
%   Example
%   -------
%   Locate and display two peaks in the Hough transform of the
%   rotated circuit.tif image.
%
%      I  = imread('circuit.tif');
%      BW = edge(imrotate(I,50,'crop'),'canny');
%      [H,T,R] = hough(BW);
%      P  = houghpeaks(H,2);
%      imshow(H,[],'XData',T,'YData',R,'InitialMagnification','fit');
%      xlabel('\theta'), ylabel('\rho');
%      axis on, axis normal, hold on;
%      plot(T(P(:,2)),R(P(:,1)),'s','color','white');
%
%   See also HOUGH and HOUGHLINES.%   Author: HSW
%   HARBIN INSTITUTE OF TECHNOLOGY
[h, numpeaks, threshold, nhood] = parseInputs(varargin{:});
% h: radon 变换的输出
% numpeaks: 峰值的个数
% threshold: 峰值的最小值, 默认为0.5*max(H(:))
% nhood: 包含两个奇数的数组[M,N], 当峰值识别出来后,设置为0 % initialize the loop variables
done = false;
hnew = h;
nhood_center = (nhood-1)/2;% 抑制块的中心位置,例如nhood = [5,5], 则nhood_center = [2,2]
peaks = [];
% 循环搜索峰值
while ~done[dummy max_idx] = max(hnew(:)); %#ok寻找现有的最大值[p, q] = ind2sub(size(hnew), max_idx);p = p(1); q = q(1);if hnew(p, q) >= thresholdpeaks = [peaks; [p q]]; %#ok<AGROW> % add the peak to the list% Suppress this maximum and its close neighbors.p1 = p - nhood_center(1); p2 = p + nhood_center(1);q1 = q - nhood_center(2); q2 = q + nhood_center(2);% Throw away neighbor coordinates that are out of bounds in% the rho direction.[qq, pp] = meshgrid(q1:q2, max(p1,1):min(p2,size(h,1)));pp = pp(:); qq = qq(:);% For coordinates that are out of bounds in the theta% direction, we want to consider that H is antisymmetric% along the rho axis for theta = +/- 90 degrees.theta_too_low = find(qq < 1);qq(theta_too_low) = size(h, 2) + qq(theta_too_low);pp(theta_too_low) = size(h, 1) - pp(theta_too_low) + 1;theta_too_high = find(qq > size(h, 2));qq(theta_too_high) = qq(theta_too_high) - size(h, 2);pp(theta_too_high) = size(h, 1) - pp(theta_too_high) + 1;% Convert to linear indices to zero out all the values.hnew(sub2ind(size(hnew), pp, qq)) = 0; %设置为0 done = size(peaks,1) == numpeaks;elsedone = true;end
end%-----------------------------------------------------------------------------
function [h, numpeaks, threshold, nhood] = parseInputs(varargin)narginchk(1,6); % 参数个数小于1 大于6报错h = varargin{1};
% validateattributes(h, {'double'}, {'real', '2d', 'nonsparse', 'nonempty',...
%                    'finite', 'integer'}, ...
%                    mfilename, 'H', 1);
% hough变换的中h中的取值必然为非负整数,但是,radon变换中只能保证为非负的validateattributes(h, {'double'}, {'real', '2d', 'nonsparse', 'nonempty',...'finite'}, ...mfilename, 'H', 1);numpeaks = 1; % set default value for numpeaks峰值的默认值为1idx = 2;
if nargin > 1if ~ischar(varargin{2})numpeaks = varargin{2};validateattributes(numpeaks, {'double'}, {'real', 'scalar', 'integer', ...'positive', 'nonempty'}, mfilename, 'NUMPEAKS', 2);idx = 3;end
end% Initialize to empty
nhood = [];
threshold = [];% Process parameter-value pairs
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
validStrings = {'Threshold','NHoodSize'};if nargin > idx-1 % we have parameter/value pairsdone = false;while ~doneinput = varargin{idx};inputStr = validatestring(input, validStrings,mfilename,'PARAM',idx);idx = idx+1; %advance index to point to the VAL portion of the input if idx > narginerror(message('images:houghpeaks:valForhoughpeaksMissing', inputStr))endswitch inputStrcase 'Threshold'threshold = varargin{idx};validateattributes(threshold, {'double'}, {'real', 'scalar','nonnan' ...'nonnegative'}, mfilename, inputStr, idx);case 'NHoodSize'nhood = varargin{idx};validateattributes(nhood, {'double'}, {'real', 'vector', ...'finite','integer','positive','odd'},...mfilename, inputStr, idx);if (any(size(nhood) ~= [1,2]))error(message('images:radonpeaks:invalidNHoodSize', inputStr))endif (any(nhood > size(h)))error(message('images:radonpeaks:tooBigNHoodSize', inputStr))end     otherwise%should never get hereerror(message('images:radonpeaks:internalError'))endif idx >= nargindone = true;endidx=idx+1;end
end% Set the defaults if necessary
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if isempty(nhood)nhood = size(h)/50; nhood = max(2*ceil(nhood/2) + 1, 1); % Make sure the nhood size is odd.确保nhood为奇数
endif isempty(threshold)threshold = 0.5 * max(h(:)); %设置默认值
end

3. 模型效果

3.1 Hough变换直线检测(Matlab内建函数)

3.2 Radon变换直线检测

3.3 合击-分进直线检测

直线检测——Radon变换/霍夫变换/基于快速傅里叶变换的直线检测相关推荐

  1. 【深度学习目标检测】一、基于yolov3的水果商品检测分类

    [深度学习目标检测]一.基于yolov3的水果商品检测分类 本文的目标是使用yolov3目标检测算法实现水果检测,使用的深度学习框架为paddlepaddle,目标检测算法框架paddledetect ...

  2. 【CT算法,radon变换】基于MATLAB的CT算法,radon变换的三维建模仿真

    1.软件版本 MATLAB2021a 2.本算法理论知识 1.输入:T(x,y,z) 使用stl读取函数完成T的导入工作 2.做Radon变换,得投影图:P 正常Radon变换即可. 3.对P:应用斜 ...

  3. 基于快速傅里叶变换实现的狗声识别器(人工智能)

    开发背景 市场上很多宠物狗狗翻译器,猫语翻译器,动物交流器,它们没有采用正确的技术去实现,从而让动物声音翻译器变成人们笑料的工具.本人为了改变现状,刚好被裁员在家里休息,所以努力开发一款真正意义上能识 ...

  4. 文本检测算法新思路:基于区域重组的文本检测

    摘要:文本检测是文本读取识别的第一步,对后续的文本识别有着重大的影响.本文主要介绍基于区域重组的文本检测算法. 本文分享自华为云社区<技术综述十三:弯曲文本检测算法(一)>,作者: 我想静 ...

  5. 输电线缺陷检测 计算机工程与设计,基于计算机视觉的焊点缺陷检测系统的设计...

    摘要: Because of unmaturity technology in the pipeline of the spot welding machine,problems such as so ...

  6. OpenCV快速傅里叶变换(FFT)用于图像和视讯流的模糊检测

    OpenCV快速傅里叶变换(FFT)用于图像和视频流的模糊检测 翻译自[OpenCV Fast Fourier Transform (FFT) for blur detection in images ...

  7. 基于matlab的霍夫变换,基于matlab的霍夫变换

    MATLAB 三维绘图功能 Plot3函数(三维曲线图) Mesh函数(网格图) Surf函数(曲面...步骤: 1.利用hough()函数执行霍夫变换,得到霍夫矩阵; 2.利用houghpeaks( ...

  8. Hough变换与Radon变换的联系与区别

    Hough变换与Radon变换的联系与区别 Hough变换把图像空间中给定的曲线按曲线的参数表达式变换成参数空间中的点,然后通过在参数空间中寻找峰值来达到在图像空间中寻找曲线的目的.可以使用Hough ...

  9. Radon变换理论介绍与matlab实现--经验交流

    本人最近在研究Radon变换,在查阅了各种资料之后在此写下个人的理解,希望与各位牛牛进行交流共同进步,也使得理解更加深刻些. Radon变换的本质是将原来的函数做了一个空间转换,即,将原来的XY平面内 ...

最新文章

  1. 数字加密c语言程序_大厂程序员整理的 C++ 资源大全,不私藏了,都送给你们吧...
  2. QT5利用chromium内核与HTML页面交互
  3. html5简单游戏案例,HTML5存储(带一个粗糙的打怪小游戏案例)
  4. 重装系统 计算机意外遇到错误无法运行,win7系统重装笔记本提示"计算机意外的重新启动或遇到错误"的解决方法...
  5. 使用t-sql语句修改表中的某些数据及数据类型。_Java面试——数据库知识点
  6. PowerDesigner导入SQL脚本
  7. Linux下访问window挂载的磁盘
  8. leetcode 435. 无重叠区间
  9. 动态路由 RIP的配置方法
  10. SiteMesh框架统一布局用法介绍
  11. CAD中的曲线长度如何测量?
  12. 计算机公式上下左右,十五个常用函数公式,值得收藏
  13. python mp4提取音频_Python从视频文件中提取wav
  14. 笔记本可以连wifi,但很卡或者无法访问互联网的一种解决方法
  15. leetcode之动态规划刷题总结1(Java)
  16. css3中的属性选择器有哪些,CSS3中属性选择器使用方法详解
  17. 软件开发随笔系列一——分布式架构实现
  18. spring boot静态资源文件的访问以及自定义
  19. 64位系统下同时使用64位和32位的eclipse
  20. 数据库的视图,视图的更新,视图的可操作性

热门文章

  1. 本机器禁止访问mysql服务器_限制指定机器IP访问oracle数据库
  2. 问题 G: 流连人间的苏苏
  3. MySQL千万级别表数据中提高RAND随机查询的实验
  4. Qt编写可视化大屏电子看板系统1-布局方案
  5. 正压控制单元KA5000F/风机节能仪KA5000F
  6. Ubuntu的商业模式
  7. 升学教育过程中:关于收费、退费的规定
  8. 阿里妈妈:品牌广告中的NLP算法实践
  9. 首次使用Neptune3000海底静力触探CPT记录
  10. uniapp 显示消息提示框 操作