- Pre-processing Enhancements: Use “adapthisteq” for local contrast enhancement and apply a Gaussian filter “imgaussfilt” for noise reduction.
- Edge Detection Improvement: Experiment with threshold and sigma values in the Canny method. Consider other methods like Sobel or Prewitt if Canny isn't effective.
- Handling Grooves and Anomalies: Use morphological operations “imdilate”, “imerode” to smooth out edges and apply “regionprops” or “bwconncomp” to exclude anomalies based on size or shape.
- Edge Refinement and Function Fitting: Use robust fitting methods (e.g., “fit” function with robust options) for curve fitting. Implement edge linking techniques to interpolate missing segments.
Edge Detection of Numerous Similar Black and White Images
1 view (last 30 days)
Show older comments
Hello dear community,
I'm new to MATLAB and I'm working on an image recognition project where I need to read image files of a component and identify certain edges.
The images are from various components of the same series and are similarly aligned, but they exhibit slight differences in their shapes (for example, if one were to overlay a function, it would vary each time). Additionally, the lighting conditions in the images are not consistent. Furthermore, some components have additional grooves that affect the identification of certain edges.
I have already developed a MATLAB code that works in some cases but is not consistent enough to reliably detect the edges of all components, especially when they exhibit anomalies. Additionally, in some cases, certain edges, such as the corner between the curve and the line in the images, are not identifiable. Hence, I have considered using data from this part of the previous image in such cases.
I have inserted several example images, one of which demonstrates how the evaluation should generally appear, and another where my approach works, as well as the special cases where my code fails.
I would greatly appreciate your help in improving my code to handle these cases or, if my approach doesn't make sense, assisting me in developing a new one ^^.
warning off
% The code should recognize the upper edges of the object on the image.
% Here I wanted to create functions that can touch up the edges and with which they can be displayed
% Short summary of the program:
% - First, the image that is recognized is uploaded and the contrasts are increased
% - Outer lines are filtered
% - The area to be searched for white pixels is restricted
% - Pixels are searched for and coordinates are saved in arrays
% - The array with the pixels is split into three new ones
% --> Split follows certain conditions that were previously defined
% - Functions for the three sub-areas are determined
% - Functions are cut to each other
import = imread(filename);
high_contrast = imadjust(import, [0;1], [0;1]); % Increase contrast
edges = imclose(edge(high_contrast,'canny'), strel('line', 5 , 0)); % Connecting the lines of the edges
fill = imfill(edges, 'holes'); % Fill in holes
bin_x = bwareaopen(fill, 50000); % Remove pixel clusters that have less than a certain number (50000)
% Creates image with outlines
se1 = strel('disk', 4, 0);
erod_x = imerode(bin_x, se1);
outlines = bin_x - erod_x;
figure, imshow(outlines);
%% Narrowing the search radius of white pixels with functions
hold on
%Function 1 (blue)
x_border = 0:1:2592;
y_blue = 0.15*x_border+1100;
plot(x_border,y_blue, 'LineWidth', 4, 'Color', 'b'); % Only for visible delimitation
% Function 2 (red)
y_red = 2.5*x_border;
plot(x_border,y_red, 'LineWidth', 4, 'Color', 'r'); % Only for visible delimitation
space_array = 0;
hold on
%figure, imshow(outlines);
for i = 150 :10: 1380 % i goes in y-direction % Checks only every 10th line
% Numerical limits set by trial and error during grinding
for q = 350 :5: 2200 % q goes in x-direction
if i < 2.5*q && i < 0.15*q+1100 % Test whether the pixels are below the two functions
if outlines(i,q) == 1 % Checks whether pixel is white and then assigns the appropriate points (determined by q and i)
space_array = space_array + 1;
x_pixel(space_array) = q;
y_pixel(space_array) = i;
end
end
end
end
hold on
% for b = 1: length(y_pixel) % Show points
% plot(x_pixel(b), y_pixel(b),'o' , 'MarkerSize', 4 , 'Color', 'g');
% % disp(b);
% end
%% Split the functions into individual areas so that one function can be created per area
for i = 1: length(x_pixel) - 1
diff_2x_points(i) = abs(x_pixel(i +1) - x_pixel(i)); % Calculates the difference between two consecutive values in the array
diff_2y_points(i) = abs(y_pixel(i + 1) - y_pixel(i));
points_gap(i) = sqrt((x_pixel(i+1) - x_pixel(i))^2 + (y_pixel(i+1) - y_pixel(i))^2); % Calculates the distance between two consecutive points (not used)
% Calculates gradient
gradient(i) = (y_pixel(i) - y_pixel(i + 1)) / (x_pixel(i) - x_pixel(i + 1));
vector1 = [x_pixel(i), y_pixel(i)];
vector2 = [x_pixel(i + 1), y_pixel(i + 1)];
dot_produkt = dot(vector1, vector2);
length_v1 = norm(vector1); % Calculates length of vectors
length_v2 = norm(vector2);
angle_vectors(i) = acosd(dot_produkt/ (length_v1 * length_v2)); %Calculates angles between the two vectors
end
% Loop for calculating the difference slope
for i = 1: length(diff_2x_points) - 1
diff_slope_amount(i) = abs(gradient(i) - gradient(i + 1));
end
diff_slope_amount(length(gradient)) = NaN; % Sets the last value of the array to NaN so that the next loop works
hold on
curve_value = 1;
line_value = 1;
corner_value = 1;
% Classification of the points in different arrays
for c = 1 : length(diff_2x_points)
% Corner assignment (between the curve and the line)
if x_pixel(c) > 630 && abs(gradient(c)) >= 1
corner_x(corner_value) = x_pixel(c);
corner_y(corner_value) = y_pixel(c);
%plot(x_pixel(c), y_pixel(c),'o' , 'MarkerSize', 4 , 'Color', 'm');
corner_value = corner_value +1;
% Assignment line
elseif y_pixel(c) > 1090 && diff_2x_points(c) >= 25 && diff_slope_amount(c) < 0.7
line_x(line_value) = x_pixel(c);
line_y(line_value) = y_pixel(c);
%plot(x_pixel(c), y_pixel(c),'o' , 'MarkerSize', 4 , 'Color', 'r');
line_value = line_value + 1;
% Curve assignment
elseif x_pixel(c) <= 780 && diff_2x_points(c) <= 20 && diff_2x_points(c) >= 5 && diff_slope_amount(c) > 0.5
curve_x(curve_value) = x_pixel(c);
curve_y(curve_value) = y_pixel(c);
%plot(x_pixel(c), y_pixel(c),'o' , 'MarkerSize', 4 , 'Color', 'b');
curve_value = curve_value + 1;
end
end
%% Create line with polyfit
% - Adapt functions with polyfit to points in the arrays
% - Then extend functions so that they also go beyond the points
hold on
one = polyfit(line_x, line_y,2); % Searches function 2. degree that fits the line
y1 = polyval(one, line_x);
%plot(line_x, y1,'LineWidth', 2 ,'Color', 'y');
function_line = @(x) one(1)*x.^2 + one(2)*x + one(3); % Function with which you can make calculations % Is created from fitted function
function_line_disp = sprintf('f(x) = %.4fx^2 + %.4fx + %.4f', one(1), one(2), one(3)); % Function that can be output as an equation
%fplot(function_line);
%% Create with polyfit function for corner
hold on
two = polyfit(corner_x, corner_y, 2);
y2 = polyval(two, corner_x);
%plot(corner_x, y2,'LineWidth', 2 ,'Color', 'm');
function_corner = @(x) two(1)*x.^2 + two(2)*x + two(3);
function_corner_disp = sprintf('f(x) = %.4fx^2 + %.4fx + %.4f', two(1), two(2), two(3));
%fplot(fuction_corner);
%% Determine curve function
%% Test rotating points
% - Rotate points so that you can use polyfit for a quadratic function
% - Determine these and then have them plotted
% - Go through points on function and rotate them, then save in array
% - Then to determine boundaries between functions (or rather points),
% check from which x_value these points and the paragraph function overlap
% --> Set the point as the initial value for the corner function
% --> Delete all points after this x_value in the array for the curve
% => Re-plot the function and the array
rotation_point = [1000 620]; % Point around which the rotation takes place
rotation_angle = 90; % Angle in degrees
for i = 1: length(curve_x) % Loop that rotates all points belonging to the array for the curve
turned_x(i) = ((curve_x(i) - rotation_point(1)) * cosd(-rotation_angle) - (curve_y(i) - rotation_point(2)) * sind(-rotation_angle) + rotation_point(1));
turned_y(i) = ((curve_x(i) - rotation_point(1)) * sind(-rotation_angle) + (curve_y(i) - rotation_point(2)) * cosd(-rotation_angle) + rotation_point(2));
end
%plot(turned_x, turned_y, 'x', 'Color', 'y');
hold on
three = polyfit(turned_x, turned_y, 8);
y3 = polyval(three, turned_x);
%plot(turned_x, y3,'LineWidth', 2 ,'Color', 'y');
function_curve = @(x) three(1)*x.^8 + three(2)*x.^7 + three(3)*x.^6 + three(4)*x.^5 + three(5)*x.^4 + three(6)*x.^3 + three(7)*x.^2 + three(8)*x + three(9) ;
function_curve_disp = sprintf('f(x) = %.4fx^8 + %.4fx^7 + %.4fx^6 + %.4fx^5 + %.4fx^4 + %.4fx^3 + %.4fx^2 + %.4fx + %.4f', three(1), three(2), three(3), three(4), three(5), three(6), three(7), three(8), three(9));
%disp(function_curve_disp);
%fplot(function_curve);
% Rotate points back
x_min = 500; % Limiting the area in which points are searched for
x_max = 1500;
numpoints = 1500;
x_values = linspace(x_min, x_max, numpoints);
y_values = function_curve(x_values); % Search for points on the curve function
original_x = (x_values - rotation_point(1)) * cosd(rotation_angle) - (y_values - rotation_point(2)) * sind(rotation_angle) + rotation_point(1); % Rotates the points to the previous position
original_y = (x_values - rotation_point(1)) * sind(rotation_angle) + (y_values - rotation_point(2)) * cosd(rotation_angle) + rotation_point(2);
original_point = [original_x', original_y'];
% for i = 1 : length(original_y)
% plot(original_x(i), original_y(i), 'pg');
% end
%% Crop functions
%% Adjust line and corner
diff_line_corner = @(x) function_line(x) - function_corner(x);
intersection_point_l_c = fzero(diff_line_corner, 735); % 735 is the starting value of the search % Search intersection point
fplot(function_line, [intersection_point_l_c 2292], 'LineWidth', 2); % Plots line only up to the intersection point
%% Adjust curve and corner
y_values_corner = function_corner(original_point(:,1)); % Finds the y-values of the corner function for the x-values of the original points
tollerance_intersection_point = 1.5;
intersect_points = [];
% Should find the rough intersections of the function and the array
for i = 1 : length(original_y)
if abs(original_y(i) - y_values_corner(i)) < tollerance_intersection_point % The y-values of the curve and those of the corner are subtracted from each other and should be smaller than the tolerance
intersect_points = [intersect_points; original_point(i,:)];
end
end
% Assigns no more values to your array where the values for the curve are to be stored after the intersection point
for i = 1 : length(original_y)
if original_y(i) >= 1000 && original_x(i) > intersect_points(2)
cut_curve_x(i) = NaN;
cut_curve_y(i) = NaN;
else
cut_curve_x(i) = original_x(i);
cut_curve_y(i) = original_y(i);
end
end
plot(cut_curve_x, cut_curve_y, '-', 'LineWidth', 2);
fplot(function_corner, [intersect_points(2) intersection_point_l_c], 'LineWidth', 2);
% Should close the small gap between the curve and corner function
start_corner_y = function_corner(intersect_points(2)); % Finds the start value of the corner function
% Finds the y-value where the function of the curve ends
for i = 1 : length(cut_curve_y)
if cut_curve_x(i) == intersect_points(2)
end_curve_y = cut_curve_y(i);
end
end
plot([intersect_points(2), intersect_points(2)], [start_corner_y, end_curve_y], '-', 'LineWidth', 2);
0 Comments
Answers (1)
Abhinaya Kennedy
on 27 Mar 2024
Hi,
I understand you would like to enhance your code. You can try the following suggestions which aim for a balance between improving edge detection accuracy and addressing specific challenges like varying lighting conditions and additional grooves.
Here is an example code snippet that implements the afore mentioned suggestions:
high_contrast = adapthisteq(imread(filename));
smoothed = imgaussfilt(high_contrast, 2);
edges = edge(smoothed,"canny");
Hope this helps!
0 Comments
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!