在MATLAB中将Regionprops输出到csv

时间:2016-01-25 16:31:33

标签: image matlab csv image-processing data-extraction

我目前正在对很多图片进行一些数据分析,我运行的代码如下:

close all
clear all
clc

A=imread('Ring_1_frame_120.jpg');       %Load picture
                                        %A01-A010 = xmin ymin width height 
                                        %for all vials
A001=imcrop(A,[65 159 95 332]);
A002=imcrop(A,[182 161 95 332]);
A003=imcrop(A,[297 164 95 332]);
A004=imcrop(A,[402 165 90 332]);
A005=imcrop(A,[495 168 90 332]);
A006=imcrop(A,[606 166 90 332]);
A007=imcrop(A,[705 171 90 332]);
A008=imcrop(A,[808 175 90 332]);
A009=imcrop(A,[922 175 90 332]);
A0010=imcrop(A,[1031 175 90 332]);

w = who; % returns the names of all your current variables in a cell.

for i = 1:numel(w)
    % A00 is unique to all the variables you want to process.
    if ~isempty(strfind(w{i}, 'A00')) 
        % hard coding greenChannel and extracting the second plane.
        eval(['greenChannel = ',w{i},'(:,:,2)']); 
        BW = edge(greenChannel,'Prewitt');
           %figure, imshow(BW);

    %Dialate Lines
       se90 = strel('line', 3, 90);
       se0 = strel('line', 3, 0);
       BWsdil = imdilate(BW, [se90 se0]);
            %figure, imshow(BWsdil), title('dilated gradient mask');

    %Fill Lines
      BWdfill = imfill(BWsdil, 'holes');
            %figure, imshow(BWdfill), title('binary image with filled holes');
    %Clean up borders  
      BWnobord = imclearborder(BWdfill, 4);
            %figure, imshow(BWnobord), title('cleared border image');
    %Final cleanup
      seD = strel('diamond',1);
      BWfinal = imerode(BWnobord,seD);
      BWfinal = imerode(BWfinal,seD);
            figure, imshow(BWfinal), title('segmented image');

      L = bwlabel(BWfinal);
      s = regionprops(L,'centroid');
      data(:,:,i) = s; %save the xy coords as data matrix 
    end
end

我想要实现的目标是将变量s变为csv文件,但由于它不起作用,我被困在最后一行。它会一直覆盖自己。 s是一个范围从3x1到5x1的结构,我也尝试使用struct2cell和mat2cell,但这是不成功的。

2 个答案:

答案 0 :(得分:3)

s结构,因此您需要做的是解压缩结构以使其成为矩阵,然后您可以将矩阵保存到文件中。 s包含一个名为Centroid的字段,因此您需要访问该字段。

然而,在我解决这一问题之前,检查工作区中有多少变量,这样你就可以确定你的循环必须迭代多少次....这是非常糟糕的做法。特别是如果您使用每个变量名作为单独的事件进行处理。我强烈建议您使用结构来封装此类或某种单元格数组。

如果我可以提供规范的帖子,请咨询用户Adriaanexcellent post,了解如何避免使用动态变量名称,并阐明我将要讨论的内容。

这样的东西会起作用。我将使用一个单元格数组,因为(至少对我而言)它更容易。将您想要的坐标放在2D矩阵中,其中每一行是您要处理的图像中位置的左上角以及宽度和高度(基本上适用于imcrop),然后遍历每个集合坐标并将裁剪后的图像作为单元格数组中的元素放置。单元格阵列的使用很重要,因为每个裁剪图像的尺寸不同,所以你不能在这里使用普通矩阵:

A=imread('Ring_1_frame_120.jpg');       %Load picture
                                        %A01-A010 = xmin ymin width height 

coords = [65 159 95 332; 182 161 95 332; 297 164 95 332; 402 165 90 332;...
          495 168 90 332; 606 166 90 332; 705 171 90 332; 808 175 90 332;...
          922 175 90 332; 1031 175 90 332];

numImages = size(coords,1);
images = cell(1,numImages);

for ii = 1 : numImages
    images{ii} = imcrop(A,coords(ii,:));
end

images现在是属于图像A的裁剪图像的单元格数组。要访问正确的图片,您可以使用images执行此操作:

img = images{ii};

ii是您要访问的图片编号。我想提出的另一个评论是你使用eval。在你的循环中真的不推荐......这就是我决定改变逻辑的原因。

请改为:

for ii = 1 : numImages
    % hard coding greenChannel and extracting the second plane.
    greenChannel = images{ii}(:,:,2); %// Change for green channel

    %// Now code is the same as before
    BW = edge(greenChannel,'Prewitt'); 
    %figure, imshow(BW);

    %Dilate Lines
    se90 = strel('line', 3, 90);
    se0 = strel('line', 3, 0);
    BWsdil = imdilate(BW, [se90 se0]);
    %figure, imshow(BWsdil), title('dilated gradient mask');

    %Fill Lines
    BWdfill = imfill(BWsdil, 'holes');
    %figure, imshow(BWdfill), title('binary image with filled holes');

    %Clean up borders  
    Wnobord = imclearborder(BWdfill, 4);
    %figure, imshow(BWnobord), title('cleared border image');

    %Final cleanup
    seD = strel('diamond',1);
    BWfinal = imerode(BWnobord,seD);
    BWfinal = imerode(BWfinal,seD);
    figure, imshow(BWfinal), title('segmented image');

   ...
end

好的,那么现在我们如何获得质心的坐标并将它们保存到文件中?您只需要解压缩结构并获得质心坐标。确保在顶部声明data现在是一个单元格数组:

data = cell(1, numImages);

你需要一个单元格数组(再次)的原因是因为你不知道你正在查看的每个裁剪图像有多少分段组件。现在终于在循环结束时了:

for ii = 1 : numImages
   %// Your code...
   %//...

   L = bwlabel(BWfinal);
   s = regionprops(L,'centroid');

   %// New code
   data{ii} = reshape([s.Centroid],2,[]).';
end

现在每个裁剪图像都有一个存储在单元格数组中的质心坐标,您可以创建多个CSV,其中每个CSV包含每个裁剪图像的每个检测到的对象的质心,或者您可以将所有质心连接在一起单个矩阵。

所以,做其中之一:

for ii = 1 : numImages
    csvwrite(sprintf('data%d.csv', ii), data{ii});
end

......或

out = cat(1, data{:});
csvwrite('data.csv', out);

我不确定您要使用哪种方法写入文件,但其中任何一种方法都可以使用。

答案 1 :(得分:0)

您需要使用s(i).Centroid作为最小示例访问struct元素

a =imread('circlesBrightDark.png');
bw = a < 100;
s = regionprops(bw,'centroid');

for i =1:size(s)
    data(:,:,i) = s(i).Centroid
end