Search code examples
matlabimage-processingimage-segmentationhough-transform

Removing colored lines in Matlab


I am attempting to delete colored lines (specifically a yellow and blue line) within a series of images in Matlab. An example image can be found here:

enter image description here

I am able to segment out the blue line segments using basic thresholding. I am also able to segment out the bright yellow circles within the yellow line segment using thresholding. Finally, I am working on removing the remaining elements of the line segment using a hough transform w/ the houghlines function and a mask.

Is there a more elegant way to perform this, or am I stuck employing this combination of methods?

Thanks

Edit: I discovered that the hough transform is only removing single pixels from my image and not the entire yellow line. I was contemplating dilating around the detected pixels and checking for similarity, but I'm worried that the yellow line is too similar to the background colors (it's position could change such that it is not fully tracking the dark background it happens to be over now). Any suggestions would be greatly appreciated.

%% This block was intended to deal with another data 
set this function has to analyze, but it actually ended up removing my 
yellow circles as well, making a further threshold step unnecessary so far 

% Converts to a binary image containing almost exclusively lines and crosshairs
mask = im2bw(rgb_img, 0.8);

% Invert mask
mask = ~mask;

% Remove detected lines and crosshairs by setting to 0
rgb_img(repmat(~mask, [1, 1, 3])) = 0;

%% Removes blue targetting lines if present

% Define thresholds for RGB channel 3 based on histogram settings to remove
% blue lines

channel3Min = 0.000;
channel3Max = 0.478;

% Create mask based on chosen histogram thresholds
noBlue = (rgb_img(:,:,3) >= channel3Min ) & (rgb_img(:,:,3) <= channel3Max);

% Set background pixels where noBlue is false to zero.
rgb_img(repmat(~noBlue,[1 1 3])) = 0;

%% Removes any other targetting lines if present

imageGreyed = rgb2gray(rgb_img);

% Performs canny edge detection
BW = edge(imageGreyed, 'canny');

% Computes the hough transform
[H,theta,rho] = hough(BW);

% Finds the peaks in the hough matrix
P = houghpeaks(H,5,'threshold',ceil(0.3*max(H(:))));

% Finds any large lines present in the image
lines = houghlines(BW,theta,rho,P,'FillGap',5,'MinLength',100);

colEnd = [];
rowEnd = [];

for i = 1:length(lines)

    % Extracts line start and end points from houghlines output

    pointHold = lines(i).point1;
    colEnd = [colEnd pointHold(1)];
    rowEnd = [rowEnd pointHold(2)];

    pointHold = lines(i).point2;
    colEnd = [colEnd pointHold(1)];
    rowEnd = [rowEnd pointHold(2)];

    % Creates a line segment from the line endpoints using a simple linear regression
    fit = polyfit(colEnd, rowEnd, 1);

    % Creates index of "x" (column) values to be fed into regression
    colIndex = (colEnd(1):colEnd(2));

    rowIndex = [];

    % Obtains "y" (row) pixel values from regression

    for i = colIndex

        rowHold = fit(1) * i + fit(2);
        rowIndex = [rowIndex rowHold];

    end

    % Round regression output
    rowIndex = round(rowIndex);

    % Assemble coordinate matrix
    lineCoordinates = [colIndex; rowIndex]';

    rgbDim = size(rgb_img);

    % Create mask based on input image size
    yellowMask = ones(rgbDim(1), rgbDim(2));

    for i = 1:length(rowIndex)

        yellowMask(rowIndex(i), colIndex(i)) = 0;

    end

    % Remove the lines found by hough transform
    rgb_img(repmat(~yellowMask,[1 1 3])) = 0;

end 

end

Solution

  • It turns out that the answer involved converting the image into the Lab colorspace and performing treshholding. This segmented out the lines with minimal loss in the rest of the image. The code is below:

        % Convert RGB image to L*a*b color space for thresholding
        rgb_img = im2double(rgb_img);
        cform = makecform('srgb2lab', 'AdaptedWhitePoint', whitepoint('D65'));
        I = applycform(rgb_img,cform);
    
        % Define thresholds for channel 2 based on histogram settings
        channel2Min = -1.970;
        channel2Max = 48.061;
    
        % Create mask based on chosen histogram threshold
        BW = (I(:,:,2) <= channel2Min ) | (I(:,:,2) >= channel2Max);
    
        % Determines the eccentricity for regions of pixels; basically how line-like
        % (vals close to 1) or circular (vals close to 0) the region is
        rp = regionprops(BW, 'PixelIdxList', 'Eccentricity');
    
        % Selects for regions which are not line segments (areas which
        % may have been incorrectly thresholded out with the crosshairs)
        rp = rp([rp.Eccentricity] < 0.99); 
    
        % Removes the non-line segment regions from the mask
        BW(vertcat(rp.PixelIdxList)) = false;
    
        % Set background pixels where BW is false to zero.
        rgb_img(repmat(BW,[1 1 3])) = 0;