4

I'm trying to detect seams in welding images for an autonomous welding process. enter image description here I want to find pixel positions of the detected line (the red line in the desired image) in the original image.

I used the following code and finally removed noise from the image to reach the result below.

clc,clear,clf;
im = imread('https://i.stack.imgur.com/UJcKA.png');
imshow(im);title('Original image'); pause(0.5);
sim = edge(im, 'sobel');
imshow(sim);title('after Sobel'); pause(0.5);
mask = im > 5;
se = strel('square', 5);
mask_s = imerode(mask, se);
mask(mask_s) = false;
mask = imdilate(mask, se);
sim(mask) = false;
imshow(sim);title('after mask');pause(0.5);
sim= medfilt2(sim);
imshow(sim);title('after noise removal')

enter image description here

Unfortunately there is nothing remaining in the image to find the seam perfectly.

Any help would be appreciated.

Download Original image.

Shai
  • 111,146
  • 38
  • 238
  • 371
asys
  • 667
  • 5
  • 20
  • 2
    any reason why you only have a < 300x300 resolution across your target object? and why does the image look so aweful? is that laser triangulation output or what? your use of the median filter on a 1-2 pixel line as a last step to remove noise shows that you have absolutely no idea what you are doing. please do yourself a favour get some basic knowledge about image processing befor you go on. – Piglet Dec 19 '16 at 22:10
  • Do you know the approximate shape of the seam in advance? Or that there is only one seam per image? Or any other helpful constraints? – Cecilia Dec 19 '16 at 22:38
  • @Cecilia There is only one seam per image. – asys Dec 20 '16 at 04:01
  • @asys +1 for the presentation! – Shai Dec 20 '16 at 10:37

2 Answers2

3

You need to make your filter more robust to noise. This can be done by giving it a larger support:

filter = [ones(2,9);zeros(1,9);-ones(2,9)];
msk = imerode(im > 0, ones(11));  % only object pixels, discarding BG
fim =imfilter(im,filter); 
robust = bwmorph((fim>0.75).*msk,'skel',inf); % get only strong pixels

The robust mask looks like:

enter image description here

As you can see, the seam line is well detected, we just need to pick it as the largest connected component:

st = regionprops(bwlabel(robust,8), 'Area', 'PixelList');
[ma mxi] = max([st.Area]); % select the region with the largest area

Now we can fit a polygon (2nd degree) to the seem:

pp=polyfit(st(mxi).PixelList(:,1), st(mxi).PixelList(:,2), 2);

And here it is over the image:

imshow(im, 'border','tight');hold on;
xx=1:size(im,2);plot(xx,polyval(pp,xx)+2,'r');

enter image description here

Note the +2 Y offset due to filter width.


PS,
You might find this thread relevant.

Community
  • 1
  • 1
Shai
  • 111,146
  • 38
  • 238
  • 371
3

Shai gives a great answer, but I wanted to add a bit more context about why your noise filtering doesn't work.

Why median filtering doesn't work

Wikipedia suggests that median filtering removes noise while preserving edges, which is why you might have chosen to use it. However, in your case it will almost certainly not work, here's why:

Median filtering slides a window across the image. In each area, it replaces the central pixel with the median value from the surrounding window. medfilt2 uses a 3x3 window by default. Let's look at a 3x3 block near your line,

Location of window

A 3x3 block around [212 157] looks like this

 [0 0 0
  1 1 1
  0 0 0]

The median value is 0! So even though we're in the middle of a line segment, the pixel will be filtered out.

The alternative to median filtering

Shai's method for removing noise instead finds the largest connected group of pixels and ignores smaller groups of pixels. If you also wanted to remove these small groups from your image, Matlab provides a filter bwareaopen which removes small objects from binary images.

For example, if you replace your line

sim= medfilt2(sim);

with

sim= bwareaopen(sim, 4);

The result is much better

after noise removal

Alternative edge detectors

One last note, Shai uses a horizontal gradient filter to find horizontal edges in your image. It works great because your edge is horizontal. If you edge will not always be horizontal, you might want to use another edge detection method. In your original code, you use Sobel, but Matlab provides many options, all of which perform better if you tune their thresholds. As an example, in the following image, I've highlighted the pixels selected by your code (with bwareaopen modification) using four different edge detectors.

Detector comparison

Cecilia
  • 4,512
  • 3
  • 32
  • 75
  • very nice explanation. One note, it is worth while noting the difference between **edge** detection and **ridge** detection. While looking at the original image, the seam is an **edge**, after applying edge detection filter the edge pixels form a **ridge** in the edge map. Therefore, while applying median filter to the original image might reduce noise and enhance the edge, applying median filter to the edge map eliminates **ridges** and makes edge detection much harder. – Shai Dec 21 '16 at 17:46