问题
I'm using Matlab R2017a and I have a RGB image (TIFF 128x128 uint16), shown below as a png image:
Actual TIFF image: http://s000.tinyupload.com/index.php?file_id=13823805859248753003
As shown above, there's a repeating pattern of really light pixels (yellow and light blue). Because I'm using pixel data, the really light pixels are skewing my graphs, so I want to "neutralize" them. I looked everywhere but I couldn't find a clean pattern recognition/removal set of commands, so I ended up finding the rows in the image where there were more than 10 pixels with intensity value > 1036 - there were 19 rows. From there, I found the indices where these brightest pixels occur, and stored them in a 19-cell cell array - cellarray{}. I can get those brightest pixel values by running image(cellarray{n}), where n goes from 1-19.
From here, I want to "neutralize" these super bright pixels by taking the average of the "normal" pixels above and below it. But if it is adjacent to another really bright pixel, I want its new pixel value to be the average of the closest pixels that are "normal". I hope that makes sense... Can someone help me with the code or suggest an easier method? Thanks so much!
回答1:
Two methods are proposed, one using cross correlation the other using brightness. They work with both grayscale and multiband images. You should play with the settings a bit to improve the result.
Important: fillmissing
requires Matlab 2016b or newer
Method A) Using cross correlation
This works by extracting a single occurrence of the pattern and finding the location on the images where the correlation is very high. While it provides better results than Method B, it is also more complicated and needs a bit more knowledge about what you are doing:
I = double(yourimage);
% Show image
imagesc(I)
% You have to select a part of single occurrence of the pattern (a template) on the image! See below image.
rect = round(getrect);
% In case it is a multiband image make grayscale image
if size(I,3)>1
BW = rgb2gray(I);
else
BW = I;
end
% Extract template from BW
template = BW(rect(2):rect(2)+rect(4),rect(1):rect(1)+rect(3),:);
% Show template - this is the extent you selected during "getrect"
imagesc(template)
% Calculate how much said template correlates on each pixel in the image
C = normxcorr2(template,BW);
% Remove padded borders from correlation
pad = floor(size(template)./2);
center = size(I);
C = C([false(1,pad(1)) true(1,center(1))], ...
[false(1,pad(2)) true(1,center(2))]);
% Plot the correlation
figure, surf(C), shading flat
Correlation of the template on the image. Note that it both highly correlates with the bright yellow patterns and the light blue pattern bellow.
% Get all indexes where the correlation is high. Value read from previous figure.
% The lower the cut-off value, the more pixels will be altered
idx = C>0.5;
% Dilate the idx because else masked area is too small
idx = imdilate(idx,strel('disk',1));
% Replicate them if multiband image. Does nothing if only grayscale image
idx = repmat(idx,1,1,size(I,3));
% Replace pattern pixels with NaN
I(idx) = NaN;
% Fill Nan values with 4x4 median filter
I = fillmissing(I,'movmedian',[4 4]);
% Display new image
figure; imagesc(I)
It catches both the yellow and light blue pattern but also some false positives. You have to experiment with different templates, cut-off values, dilation radii and median filter sizes to improve the result.
Method B) Using brightness of image
A bit offtopic because no pattern recognition is used but instead that the yellow patterns are just very bright. But since the result isn't too bad and a lot simpler I felt it might be useful. A lot easier to avoid finding false positives.
% I = your image
I = double(I);
% get indexes where very bright in red channel
idx = cdata(:,:,1)>157; % 157 = brightest non-pattern pixel in your image
% From now on same as end from method A)!
% dilate the idx to also get the adjacent pixels because else too few pixels will be erased
idx = imdilate(idx,strel('disk',1));
% replacate them if multiband image. Does nothing if only grayscale image
idx = repmat(idx,1,1,size(I,3));
% replace pattern pixels with NaN
I(idx) = NaN;
% fill Nan values using 50x50 median filter
I = fillmissing(I,'movmedian',[50 50]);
% display new image
figure; imagesc(I)
来源:https://stackoverflow.com/questions/45041735/detect-repetitive-pixel-patterns-in-an-image-and-remove-them-using-matlab