简体   繁体   中英

speed up matlab code for eliminating white pixels

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´?

Correct me if I'm wrong, or ignore this 'answer' entirely, but the code posted appears to:

  1. Find the most white pixel in the image (I'm guessing here, imageRGB isn't a Matlab built-in).
  2. Find the position in the image of the most white pixel (another guess, another unknown function maxPosition ).
  3. Do some sort of averaging to replace the most-white pixel with an average over its immediate neighbourhood.
  4. Repeat the process until the stopping criterion is satisfied.

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:

  • Pad the image with a 2-pixel halo all round before starting operations. Then apply your operation to all the white pixels in the original image. Obviously you'll have to set the halo pixels to the right value to leave your operation unchanged.

or

  • Operate only on the pixels in the image which are not within 2 pixels of the edge. This will produce an output image which is 4 pixels smaller in each dimension, but on large images this is often not a problem.

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.

  • From what I know 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);   

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM