问题
I have some signal images:
As you can inspect, some of them contain color signals and some are just gray/black color signals. My task is to extract pure signal with white background only. That means I need to remove all but signal in the image.
I checked that dash lines, dotted lines, solid lines (top and bottom) have the same RGB value that are close to 0;0;0 (ex: 0;0;0, 2;2;2; or 8;8;8) in terms of RGB.
Therefore, first thing that came to my mind was to access RGB values of each pixel and assign white color if all RGB values are the same. Using this heavy computation I can extract all color signals, because RGB values are never same for colors like red, blue, green (or their shades to some extent).
However, that process would remove signals where signal's pixel values are the same. That happens with mostly black color signals (the first two samples for example).
I also thought of extracting the signal if it keeps its horizontal and some vertical continuity, but to be honest I don't know how to write the code for it.
I am not asking any code solution to this challenge. I would like to have different opinions on how I can successfully extract the original signal.
I am looking forward to having your ideas, insights and sources. Thanks
Note: All of my images (about 3k) are in one folder and I am going to apply one universal algorithm to accomplish the task.
回答1:
You can find the horizontal and vertical lines using Hough transform.
After finding the lines, it's simple to erase them.
Removing the lines is only the first stage, but it looks like a good starting point...
Keeping the colored pixels (as you suggested) is also simple task.
You have mentioned you are not asking any code solution, but I decided to demonstrate my suggestion using MATLAB code:
close all
clear
origI = imread('I.png'); %Read image
I = imbinarize(rgb2gray(origI)); %Convert to binary
I = ~I; %Invert - the line color should be white.
%Apply hough transform: Find lines with angles very close to 0 degrees and with angles close to 90 degrees.
[H,theta,rho] = hough(I, 'RhoResolution', 1, 'Theta', [-0.3:0.02:0.3, -90:0.02:-89.7, 89.7:0.02:89.98]);
P = houghpeaks(H, numel(H), 'Threshold', 0.1, 'NHoodSize', [11, 1]); %Use low thresholds
lines = houghlines(I,theta,rho,P,'FillGap',25,'MinLength',200); %Fill large gaps and keep only the long lines.
%Plot the lines for debugging, and erase them by drawing black lines over them
J = im2uint8(I);
figure, imshow(I), hold on
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');
% Draw black line over each line.
J = insertShape(J, 'Line', [xy(1,1), xy(1,2), xy(2,1), xy(2,2)], 'Color', 'Black');
end
%Covert J image to binary (because MATLAB function insertShape returns RGB output).
J = imbinarize(rgb2gray(J));
figure, imshow(J)
%Color mask: 1 where color is not black or white.
I = double(origI);
C = (abs(I(:,:,1) - I(:,:,2)) > 20) | (abs(I(:,:,1) - I(:,:,3)) > 20) | (abs(I(:,:,2) - I(:,:,3)) > 20);
figure, imshow(C)
%Build a mask that combines "lines" mask and "color" mask.
Mask = J | C;
Mask = cat(3, Mask, Mask, Mask);
%Put white color where mask value is 0.
K = origI;
K(~Mask) = 255;
figure, imshow(K)
Detected lines:
Result after deleting lines:
Final result:
As you can see there are still leftovers.
I Applied a second iteration (same code) over the above result.
Result was improved:
You may try removing the leftovers using morphological operations.
It's going to be difficult without erasing the dashed graph.
Iterating all the PNG image files:
- Place the code in an
m
file (MATLAB script file). - Place the
m
file in the same folder of the PNG image files.
Here is the code:
%ExtractSignals.m
close all
clear
%List all PNG files in the working directory (where ExtractSignals.m is placed).
imagefiles = dir('*.png');
nfiles = length(imagefiles);
result_images = cell(1, nfiles); %Allocate cell array for storing output images
for ii = 1:nfiles
currentfilename = imagefiles(ii).name; %PNG file name
origI = imread(currentfilename); %Read image
%Verify origI is in RGB format (just in case...)
if (size(origI, 3) ~= 3)
error([currentfilename, ' is not RGB image format!']);
end
I = imbinarize(rgb2gray(origI)); %Convert to binary
I = ~I; %Invert - the line color should be white.
%Apply hough transform: Find lines with angles very close to 0 degrees and with angles close to 90 degrees.
[H,theta,rho] = hough(I, 'RhoResolution', 1, 'Theta', [-0.3:0.02:0.3, -90:0.02:-89.7, 89.7:0.02:89.98]);
P = houghpeaks(H, numel(H), 'Threshold', 0.1, 'NHoodSize', [11, 1]); %Use low thresholds
lines = houghlines(I,theta,rho,P,'FillGap',25,'MinLength',200); %Fill large gaps and keep only the long lines.
%Plot the lines for debugging, and erase them by drawing black lines over them
J = im2uint8(I);
%figure, imshow(I), hold on
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');
% Draw black line over each line.
J = insertShape(J, 'Line', [xy(1,1), xy(1,2), xy(2,1), xy(2,2)], 'Color', 'Black');
end
%Covert J image to binary (because MATLAB function insertShape returns RGB output).
J = imbinarize(rgb2gray(J));
%figure, imshow(J)
%Color mask: 1 where color is not black or white.
I = double(origI);
C = (abs(I(:,:,1) - I(:,:,2)) > 20) | (abs(I(:,:,1) - I(:,:,3)) > 20) | (abs(I(:,:,2) - I(:,:,3)) > 20);
%figure, imshow(C)
%Build a mask that combines "lines" mask and "color" mask.
Mask = J | C;
Mask = cat(3, Mask, Mask, Mask);
%Put white color where mask value is 0.
K = origI;
K(~Mask) = 255;
%figure, imshow(K)
%Second iteration - applied by "copy and paste" of the above code (it is recommended to use a function instead).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
origI = K; %Set origI to the result of the first iteration
I = imbinarize(rgb2gray(origI)); %Convert to binary
I = ~I; %Invert - the line color should be white.
%Apply hough transform: Find lines with angles very close to 0 degrees and with angles close to 90 degrees.
[H,theta,rho] = hough(I, 'RhoResolution', 1, 'Theta', [-0.3:0.02:0.3, -90:0.02:-89.7, 89.7:0.02:89.98]);
P = houghpeaks(H, numel(H), 'Threshold', 0.1, 'NHoodSize', [11, 1]); %Use low thresholds
lines = houghlines(I,theta,rho,P,'FillGap',25,'MinLength',200); %Fill large gaps and keep only the long lines.
%Plot the lines for debugging, and erase them by drawing black lines over them
J = im2uint8(I);
%figure, imshow(I), hold on
for k = 1:length(lines)
xy = [lines(k).point1; lines(k).point2];
% Draw black line over each line.
J = insertShape(J, 'Line', [xy(1,1), xy(1,2), xy(2,1), xy(2,2)], 'Color', 'Black');
end
%Covert J image to binary (because MATLAB function insertShape returns RGB output).
J = imbinarize(rgb2gray(J));
%figure, imshow(J)
%Color mask: 1 where color is not black or white.
I = double(origI);
C = (abs(I(:,:,1) - I(:,:,2)) > 20) | (abs(I(:,:,1) - I(:,:,3)) > 20) | (abs(I(:,:,2) - I(:,:,3)) > 20);
%figure, imshow(C)
%Build a mask that combines "lines" mask and "color" mask.
Mask = J | C;
Mask = cat(3, Mask, Mask, Mask);
%Put white color where mask value is 0.
K = origI;
K(~Mask) = 255;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Store result image in a cell array
result_images{ii} = K;
end
%Display all result images
for ii = 1:nfiles
figure;
imshow(result_images{ii});
title(['Processed ', imagefiles(ii).name]);
end
来源:https://stackoverflow.com/questions/59476427/removing-background-noise-from-signal-images-rgb