需要自动消除图像中的噪声和对象的外边界

时间:2015-03-06 08:14:00

标签: image algorithm matlab opencv image-processing

我是机械工程专业的学生,​​正在研究一个项目,以自动检测车间中存在的焊缝(焊缝是要焊接的边缘)。这给出了焊接中涉及的基本术语(http://i.imgur.com/Hfwjq0w.jpg)。

enter image description here enter image description here

为了将焊件与其他物体分开,我拍摄了背景图像并减去了具有焊件的前景图像,仅对焊件进行了观察(http://i.imgur.com/v7yBWs1.jpg)。图像相减后,仍然存在减去背景的阴影,眩光和残余噪声。

enter image description here

由于我想自动识别没有焊件外边界的焊缝,我试图使用canny算法检测焊件图像中的边缘,并尝试使用bwareopen函数消除孤立的噪声。我已经以某种方式获得焊件和焊缝的近似边界。我使用的门限纯粹是试错法,因为不知道自动设置阈值来检测它们的方法。

我现在面临的问题是我无法指定一个明确的阈值,因为该算法应该能够识别任何材料的接缝,无论其表面纹理,眩光和阴影如何。我需要一些帮助来消除背景减去图像中的眩光,阴影和孤立点。

此外,我需要帮助摆脱外边界,并从起点到终点只获得平滑的焊缝。

我尝试使用以下代码:

a=imread('imageofworkpiece.jpg'); %http://i.imgur.com/3ngu235.jpg

b=imread('background.jpg'); %http://i.imgur.com/DrF6wC2.jpg

Ip = imsubtract(b,a);

imshow(Ip) % weldment separated %http://i.imgur.com/v7yBWs1.jpg

BW = rgb2gray(Ip);

c=edge(BW,'canny',0.05); % by trial and error

figure;imshow(c) % %http://i.imgur.com/1UQ8E3D.jpg

bw = bwareaopen(c, 100); % by trial and error

figure;imshow(bw) %http://i.imgur.com/Gnjy2aS.jpg

任何人都可以建议我采用自适应方式设置一个threhold并移除外边界以仅检测接缝吗?谢谢

2 个答案:

答案 0 :(得分:1)

从您的图像中看起来,焊缝看起来通常很暗,边缘强度很大,所以为什么不使用它呢?

  1. 请勿使用背景

  2. 创建派生图片

    dx[y][x]=pixel[y][x]-pixel[y][x-1]
    

    对整个图像执行此操作(如果在场,则x必须在循环中减少!!!)

  3. 过滤掉低于阈值的所有派生

    if (|dx[y][x]|<threshold) dx[y][x]=0; else pixel[y][x]=255;` // or what ever values you use
    
  4. 如何获取阈值?

    计算minmax强度,并将阈值设置为(max-min)*scale,其中scale的值低于1.0(以0.02开头或{ {1}}例如......

  5. 也为0.1

    执行此操作

    所以计算y ...并将dy[][]dx[][]组合在一起。使用dy[][]OR逻辑函数

  6. 过滤掉工件

    您可以使用形态滤镜或平滑阈值。毕竟,你将拥有焊缝像素的掩模


    如果你需要边框,那么只需遍历所有像素并记住min,max AND coords ......

  7. <强> [注释]

    如果您的图像具有良好的光照,那么您可以直接忽略推导和阈值强度,例如:

    x,y

    如果你想真正完全自动化,那么你必须使用自适应阈值。因此,在循环中尝试更多阈值,并根据几何尺寸,位置等记住最接近所需输出的结果......

    [edit1]终于有了一些时间/心情,所以

    1. 强度图像阈值

      你提供的单个图像远远不足以制作可靠的算法。这是结果

      intensity threshold

      如你所见,没有进一步处理,这不是一个好方法

    2. 派生图片阈值

      阈值推导x(10%)

      di/dx threshold

      阈值推导y(5%)

      di/dy threshold

      threshold = 0.5*(average_intensity+lowest_intensity) 10%di / dx和1.5%di / dy的组合

      di/dx AND di/dy threshold

    3. C ++ 中的代码如下所示(抱歉不要使用Matlab):

      AND


      int x,y,i,i0,i1,tr2,tr3; pic1=pic0; // copy input image pic0 to pic1 pic2=pic0; // copy input image pic0 to pic2 (just to resize to desired size for derivation) pic3=pic0; // copy input image pic0 to pic3 (just to resize to desired size for derivation) pic1.rgb2i(); // RGB -> grayscale // abs derivate by x for (y=pic1.ys-1;y>0;y--) for (x=pic1.xs-1;x>0;x--) { i0=pic1.p[y][x ].dd; i1=pic1.p[y][x-1].dd; i=i0-i1; if (i<0) i=-i; pic2.p[y][x].dd=i; } // compute min,max derivation i0=pic2.p[1][1].dd; i1=i0; for (y=1;y<pic1.ys;y++) for (x=1;x<pic1.xs;x++) { i=pic2.p[y][x].dd; if (i0>i) i0=i; if (i1<i) i1=i; } tr2=i0+((i1-i0)*100/1000); // abs derivate by y for (y=pic1.ys-1;y>0;y--) for (x=pic1.xs-1;x>0;x--) { i0=pic1.p[y ][x].dd; i1=pic1.p[y-1][x].dd; i=i0-i1; if (i<0) i=-i; pic3.p[y][x].dd=i; } // compute min,max derivation i0=pic3.p[1][1].dd; i1=i0; for (y=1;y<pic1.ys;y++) for (x=1;x<pic1.xs;x++) { i=pic3.p[y][x].dd; if (i0>i) i0=i; if (i1<i) i1=i; } tr3=i0+((i1-i0)*15/1000); // threshold the derivation images and combine them for (y=1;y<pic1.ys;y++) for (x=1;x<pic1.xs;x++) { // copy original (pic0) pixel for non thresholded areas the rest fill with green color if ((pic2.p[y][x].dd>=tr2)&&(pic3.p[y][x].dd>=tr3)) i=0x00FF00; else i=pic0.p[y][x].dd; pic1.p[y][x].dd=i; } 是输入图像
      pic0是输出图像
      pic1只是派生的临时存储
      pic2,pic3的大小为pic?.xy,pic?.ys
      pic?是像素轴(dd表示访问像素为DWORD ...)
      你可以看到周围有很多东西(在你提供的第一张图片中点头可见)所以你需要进一步处理

      • 细分并分开......,
      • 使用hough transform ...
      • 过滤掉小文物......
      • 按预期的几何属性(宽高比,位置,大小)识别对象

      自适应阈值:

      您需要知道所需的输出图像属性(不能从单个图像输入中可靠地推断出)然后创建用变量pic.p[y][x].dd进行上述处理的函数。尝试循环tr2,tr3的更多选项(遍历所有值或迭代以获得更好的结果并记住最佳输出(因此您还需要一些检测输出质量的函数),例如:

      tr2,tr3

      在此之后 quality=0.0; param=0.0; for (a=0.2;a<=0.8;a+=0.1) { pic1=process_image(pic0,a); q=detect_quality(pic1); if (q>quality) { quality=q; param=a; pico=pic1; } } 应保持相对最佳的阈值图像...您应该在process_image内单独处理所有阈值,目标阈值必须按pic1缩放,例如{{1} }

答案 1 :(得分:1)

这不能解决您找到自动阈值算法的问题。但我可以帮助隔离接缝。接缝沿着y轴(这总是这样吗?)所以我使用霍夫变换来仅隔离近垂直线。通常它会找到所有行,但我限制了theta搜索参数。我现在使用的代码恰好突出了最长的线段(我直接得到它from the matlab website)并且巧合地是焊缝。这纯属巧合。但是使用你的bwareaopened图像作为输入,霍夫线检测器能够找到接缝。当然,它需要一些玩耍才能工作,所以你会陷入原先的问题,不知何故找到最佳设置

也许这可以成为其他人的跳板 enter image description here     A = imread( 'weldment.jpg'); %http://i.imgur.com/3ngu235.jpg

b=imread('weld_bg.jpg'); %http://i.imgur.com/DrF6wC2.jpg

Ip = imsubtract(b,a);

imshow(Ip) % weldment separated %http://i.imgur.com/v7yBWs1.jpg

BW = rgb2gray(Ip);

c=edge(BW,'canny',0.05); % by trial and error
bw = bwareaopen(c, 100); % by trial and error

figure(1);imshow(c) ;title('canny') % %http://i.imgur.com/1UQ8E3D.jpg
figure(2);imshow(bw);title('bw area open') %http://i.imgur.com/Gnjy2aS.jpg

[H,T,R] = hough(bw,'RhoResolution',1,'Theta',-15:5:15);
figure(3)
imshow(H,[],'XData',T,'YData',R,...
            'InitialMagnification','fit');
xlabel('\theta'), ylabel('\rho');
axis on, axis normal, hold on;
P  = houghpeaks(H,5,'threshold',ceil(0.5*max(H(:))));
x = T(P(:,2)); y = R(P(:,1));
plot(x,y,'s','color','white');
% Find lines and plot them
lines = houghlines(BW,T,R,P,'FillGap',2,'MinLength',30);
figure(4), imshow(BW), hold on
max_len = 0;
for k = 1:length(lines)
   xy = [lines(k).point1; lines(k).point2];
   plot(xy(:,1),xy(:,2),'LineWidth',2,'Color','green');

   % Plot beginnings and ends of lines
   plot(xy(1,1),xy(1,2),'x','LineWidth',2,'Color','yellow');
   plot(xy(2,1),xy(2,2),'x','LineWidth',2,'Color','red');

   % Determine the endpoints of the longest line segment
   len = norm(lines(k).point1 - lines(k).point2);
   if ( len > max_len)
      max_len = len;
      xy_long = xy;
   end
end

% highlight the longest line segment
plot(xy_long(:,1),xy_long(:,2),'LineWidth',2,'Color','blue');