matlab:圆形的图像识别(二)

本文主要使用了matlab中的imfindcircles函数,功能参数详见其文档。其主要使用Hough变换的方法提取图片中圆形信息。

  • 使用此函数需要注意的几点:

1)当 radius(或 rmin)的值小于或等于 5 时,imfindcircles 的准确度会受到限制;

2)imfindcircles 找不到圆心位于图像区域之外的圆形;

3)imfindcircles 会预处理二值(逻辑值)图像以提高结果的准确度。在处理真彩色图像之前,它使用 rgb2gray 函数将其转换为灰度图像。

%此程序用来识别和跟踪视频中的颗粒及其轨迹



%% 读取图片信息
% %test;
% RGB= imread('F:\desktop\轨迹熵\实验\目标检测跟踪\granule4.png');
% imshow(RGB)


% 将视频拆解成图片;
video = VideoReader('E:\20220326\125-2fps.avi');
N_Frames = video.NumFrames;   %得到帧数
H = video.Height;     %得到高度
W = video.Width;      %得到宽度
Rate = video.FrameRate;
% Preallocate movie structure.
% mov(1:nFrames) = struct('cdata',zeros(H,W,3,'uint8'),'colormap',[]);
%read one frame every time
% for i = 1:1000
%     mov(i).cdata = read(video,i);
%     RGB= mov(i).cdata;   
% %     disp('当前播帧数:'),disp(i);
% %     imshow(RGB);
% end

% 由于不需要存储每张图片,所以不需要mov结构来储存数据;
%待将此处化为循环结构;


%test
i=1156810;
RGB=read(video,i);
bw=imbinarize(RGB,'global');         %imfindcircles函数本身是先把图片转为二值图,但是并不会选择性的去掉连通像素小于某一阈值的区域;
                                     %所以此步骤看似重复,但其实是为bwareaopen函数做准备;
                                     %由于图片本来就是灰度图,直接转为二值图;

bw=bwareaopen(bw,60);   %去掉连通像素小于60的区域;

%注意在识别之前,需要先取一个很大的半径范围,进而确认目标是在哪个范围之内,缩小范围,进而节省上述手动划线过程;
%如果被识别的颗粒直径有变化需要修改此参数!!!!!!!!!!!!!!!
Rmin = 7; 
Rmax = 16;
[center, radius]=imfindcircles(bw,[Rmin Rmax],'Sensitivity',0.9,'ObjectPolarity','bright');    %调节ObjectPolarity属性可以实现对不同颜色的区分;
imshow(bw);
h=viscircles(center,radius);     %显示圆形轮廓;

% immatrix=imshow(bw);        %将图片化为数值矩阵;

%数据输出的文件夹目标名;
folder_name='E:\20220326';

% %服务器上使用工作文件当前文件夹;
%待查
% folder_name=pwd;     %显示当前文件夹绝对路径字符串,当然也可以不用绝对路径;


%在当前文件夹(程序所在文件夹)创建data数据文件;
%如果文件夹已经存在,则会发出警告,但是无碍下一步操作;
% mkdir('data');      %服务器上可使用相对目录;
mkdir(strcat(folder_name,'\data' ));    

%注意在服务器下可以使用相对路径,即不使用绝对路径;
fid_position=fopen(strcat(folder_name,'\data\125-2fps_position.txt'),'w');
fid_problem=fopen(strcat(folder_name,'\data\125-2fps_position_problem.txt'),'w');

tic
for i=376841:1:739966
    RGB=read(video,i);
    bw=imbinarize(RGB,'global');    %由于图片本来就是灰度图,直接转为二值图;
                                    %此处为了提高后续的识别成功率;
                                    %多出此步骤,主要是为了后面消除连片像素小的区域,imfindcircles函数本身当然也会有二值化过程,速度
                                    %总体与之前基本持平;
                                    %默认情况下,imbinarize 使用 Otsu
                                    %方法,该方法选择特定阈值来最小化阈值化的黑白像素的类内方差;
    bw=bwareaopen(bw,60);   %去掉连通像素小于60的区域;

    %注意在识别之前,需要先取一个很大的半径范围,进而确认目标是在哪个范围之内,缩小范围,进而节省上述手动划线过程;
    %如果被识别的颗粒直径有变化需要修改此参数!!!!!!!!!!!!!!!
    Rmin = 7; 
    Rmax = 16;
    [center, radius]=imfindcircles(RGB,[Rmin Rmax],'Sensitivity',0.9,'ObjectPolarity','bright');    %调节ObjectPolarity属性可以实现对不同颜色的区分;
                                                                                                     %此处sensitivity的值在0.9附近对结果影响很敏感,0.9为一经验值;
%     disp(i);    

    if length(center)==10
        for j=1:1:10
            fprintf(fid_position,'%15.10f %15.10f\n',center(j,:));
        end     
        
    elseif length(center)>10
        disp('oh no');
%         imshow(bw);
%         h=viscircles(center,radius);     %显示圆形轮廓;
%         drawnow;
        disp(i);
        disp(center);
        %有时识别出的圆的数量大于实际数量,需要剔除多于的圆心数据;

        D=pdist(center);    %计算行与行之间的欧几里得距离;
        Z=squareform(D);    %为了方便识别行号和列号,将上述结果转为方阵,第i行j列,即代表center第i行与第j行所代表向量之间的距离;
        U=triu(Z);          %为了方便识别行号和列号,只取出矩阵的上三角部分;
        [row,col]=find(U>0 & U<10);       %如果圆心距离大于0小于10,则认为两个圆心重复;如果被识别的颗粒直径有变化需要修改此参数!!!!!!!!
        center(row,:)=[];     %任意去掉其中重复的圆心;
        if length(center)~=10
            disp(['There is a problem with this frame:',num2str(i)]);     %以防万一;
            disp(center);
            fprintf(fid_problem,'%10d\n',i);
            for j=1:1:10
                fprintf(fid_position,'%15.10f %15.10f\n',zeros(1,2));     %为了后续处理数据的方便(数据长度不发生变化),在有问题的插入0值,供后续更改;
                                                                           %注意如果被检测圆的数量发生改变,这里需要更改数目!!!!!!
            end
                        
        else
            disp('successful!!!');
            disp(center);
            for j=1:1:10
                fprintf(fid_position,'%15.10f %15.10f\n',center(j,:));
            end
        end
    %有时识别出的圆的数量小于实际数量,暂无更好的办法,此处调节识别圆的sensitivity,但是有风险;
    else
        disp(['There is a problem with this frame:',num2str(i)]);     %以防万一;
        disp(center);
        fprintf(fid_problem,'%10d\n',i);
        for j=1:1:10
            fprintf(fid_position,'%15.10f %15.10f\n',zeros(1,2));     %为了后续处理数据的方便(数据长度不发生变化),在有问题的插入0值,供后续更改;
                                                                      %注意如果被检测圆的数量发生改变,这里需要更改数目!!!!!!
        end
    end
%     imshow(bw)
%     h=viscircles(center,radius);     %显示圆形轮廓;
%     drawnow;    %为了连续显示图窗;
end

fclose(fid_position);
fclose(fid_problem);

toc




%注意检查各矩阵是否与实际颗粒的数目是否一样;


%% 将图片转为二值图片,凸显边缘

% % I = rgb2gray(RGB);   %图片本来就是灰度图片,不需要再转为灰度图;
% imhist(RGB);    %查看图片的灰度分布
% bw = imbinarize(RGB);    %由于图片本来就是灰度图,直接转为二值图;
% % imshow(bw)
% imhist(bw);    %查看图片的灰度分布
% imwrite(bw,'E:\20220326\125-2fps.png');
% 
% % 删除包含少于阈值像素的所有对象
% bw = bwareaopen(bw,60);
% imshow(bw)

% % 填充笔帽中的间隙
% se = strel('disk',2);
% bw = imclose(bw,se);
% imshow(bw)

% 
% %填充任何孔洞,以便可以使用 regionprops 来估计每个边界所包围的面积
% bw = imfill(bw,'holes');
% imshow(bw)


% %手动估算颗粒直径的长度
% d = drawline;   %在figure图中对颗粒的直径划线
% pos = d.Position;
% diffPos = diff(pos);
% diameter = hypot(diffPos(1),diffPos(2))

  • 注意此识别程序并不能完全理想的挑选出所有的圆形,程序中把异常值的情况挑选了出来,输出到了

‘E:\20220326\125-2fps_position_problem.txt’

  • 识别正常的情况:

 

 

  • 识别异常情况:

图 原始图片(灰度图片)

图 出现异常的识别结果(在灰度图下)

图 出现异常的识别结果(在二值图下)

有阴影球体图片

有阴影球体识别结果(灰度图)

有阴影球体识别结果(二值图)

参考文献:

检测圆形目标

检测和测量图像中的圆形目标

Measuring the Radius of a Roll of Tape

MATLAB: Image Prosessing Toolbox

  • 4
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
MATLAB中,可以使用图像处理工具箱中的函数来识别圆形物体及求其半径。以下是一种常用的方法: 1. 读入需要处理的图像,并将其转换为灰度图像。 ``` img = imread('circle.jpg'); img_gray = rgb2gray(img); ``` 2. 对灰度图像进行值化处理,将圆形物体转换为白色,背景转换为黑色。可以使用imbinarize函数或者自适应阈值方法来进行值化处理。 ``` img_bw = imbinarize(img_gray); ``` 3. 对值化图像进行形态学处理,去除小的噪点,并将圆形物体的边缘增强。可以使用imopen、imclose、imerode、imdilate等函数来进行形态学处理。 ``` se = strel('disk', 5); % 创建圆形结构元素 img_open = imopen(img_bw, se); % 开运算去除小的噪点 img_close = imclose(img_open, se); % 闭运算增强边缘 ``` 4. 使用圆形的霍夫变换识别圆形物体。使用houghcircles函数来进行霍夫变换,该函数返回圆心坐标和半径。 ``` [centers, radii] = imfindcircles(img_close, [20 50]); % 寻找半径在20到50之间的圆形 ``` 5. 可以使用viscircles函数将识别出的圆形在原图上进行标记。使用radii向量中的值来计算圆形的半径。 ``` imshow(img); hold on; viscircles(centers, radii,'EdgeColor','b'); hold off; radius = radii(1); % 假设只识别出一个圆形 ``` 完整的MATLAB代码如下: ``` img = imread('circle.jpg'); img_gray = rgb2gray(img); img_bw = imbinarize(img_gray); se = strel('disk', 5); img_open = imopen(img_bw, se); img_close = imclose(img_open, se); [centers, radii] = imfindcircles(img_close, [20 50]); imshow(img); hold on; viscircles(centers, radii,'EdgeColor','b'); hold off; radius = radii(1); ``` 需要注意的是,图像处理的结果可能会受到图像质量、光照条件、噪点等因素的影响,因此需要根据实际情况进行调整和优化。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值