Reputation: 3488
I have rgb images from a camera which contain white pixels. I wrote the following code to eliminate them. It works but takes forever.
% elliminate white pixel
while 1
maxValue = max(imageRGB(:));
[maxY maxX] = maxPosition(squeeze(imageRGB(:,:,c)));
surr = 2;
x_l = maxX - surr; if x_l < 1, x_l = 1; end
x_r = maxX + surr; if x_r > size(imageRGB,2), x_r = size(imageRGB,2); end
y_u = maxY - surr; if y_u < 1, y_u = 1; end
y_b = maxY + surr; if y_b > size(imageRGB,1), y_b = size(imageRGB,1); end
meanArea = ((y_b-y_u)+1) * ((x_r-x_l)+1) - 1;
mean = (sum(sum(imageRGB(y_u:y_b, x_l:x_r,c))) - maxValue)/meanArea;
if (maxValue/mean > 1.5)
imageRGB(maxY,maxX,c) = mean;
else
break;
end
end
Any ideas how to speed up this code´?
Upvotes: 0
Views: 350
Reputation: 1199
Another possibility would be to remove the sorting and just calculate the average on the whole image. This is easily done with conv2
which is a built-in and therefor very fast compared to anything anyone of us could cook up.
Assuming you are working with double gray-scale images:
% generate an averageing filter
filterMat=ones(2*filterSize+1);
filterMat=filterMat/sum(filterMat(:));
% convolve with image
meanComplete=conv2(picture,filterMat,'same');
% calculate the decision criterion
changeIndices=picture./meanComplete>relThreshold & picture>absThreshold;
% use logical indexing to replace white pixels with the mean
newPicture=picture;
newPicture(changeIndices)=mean(changeIndices);
I need 50ms for one Full-HD image.
Upvotes: 0
Reputation: 78314
Correct me if I'm wrong, or ignore this 'answer' entirely, but the code posted appears to:
imageRGB
isn't a Matlab built-in).maxPosition
).If you have the Image Processing Toolbox, you will find that it has all sorts of functions for adjusting pixel intensity which is, I think, what you are trying to do, so you can stop reading this answer now. If you don't have the toolbox, read on.
If you can, you should amend your entire approach and decide, from one read of the image, what the threshold for averaging should be. This would lift the computation of maxValue
out of the loop, maybe replace it by a single computation of thresholdValue
. Then you could lift the calculation of [maxY maxX]
out of the loop too.
If you can't do this, there are still some options for increasing the speed of your operations. You could either:
or
Either of these eliminates a whole slew of if
statements and the repeated calculation of meanArea
(since it becomes a constant).
If you can calculate a threshold once, at the start of processing, rather than recalculating it iteratively you might find that you can write a function to implement the averaging which you can apply to all the pixels in the image, and eliminate the need to find the white pixels. The function would have to leave the un-white pixels unchanged of course. Applying an operation to every pixel, ensuring that it is a null-operation for the pixels which should not be changed (or an identity operation for those pixels) is sometimes faster than first finding the pixels that need to be changed and then applying the operation only to those pixels.
Upvotes: 2
Reputation: 4732
if
perform poorly.you could replace
x_l = maxX - surr; if x_l < 1, x_l = 1; end
with
x_l = max(maxX - surr,1);
and the others analogous.
Also you could put the (maxValue/mean > 1.5)
in the condition for the while loop.
in the lines
maxValue = max(imageRGB(:));
[maxY maxX] = maxPosition(squeeze(imageRGB(:,:,c)));
you search for max twice. I suppose you could save some time if you write it like:
[maxY maxX] = maxPosition(squeeze(imageRGB(:,:,c)));
maxValue = imageRGB(maxY,maxX,c);
Upvotes: 1