Shankar Kumar
Shankar Kumar

Reputation: 2357

Flipping Around 5 percent of 1's and 0's

For the following letter, I wish to add noise to it by changing 5 percent of the 1's into 0's. So far, I have the following code which turns them all into 0's. Can someone please point me in the right direction? Thank you!

letterA = [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ...
           0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ...
           0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ...
           0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ...
           0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ...
           0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 ...
           0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 ...
           0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 ...
           0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 ...
           0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 ...
           0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 ...
           0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 ...
           0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 ...
           0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 ...
           0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 ...
           0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 ...
           0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 ...
           0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 ...
           0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]; 

for i=1:numel(letterA)
    if letterA(i)==1
        letterA(i)=0;
    end
end

disp(letterA)

Upvotes: 2

Views: 170

Answers (3)

Eitan T
Eitan T

Reputation: 32920

The basic approach is to find the indices of the 1's and count them, randomly pick a desired amount of indices out of them, and then operate on them:

one_flip_ratio = 0.05;
idx_ones = find(letterA == 1);                          %// Indices of 1's
flips = round(one_flip_ratio * numel(idx_ones));        %// Number of flips
idx_flips = idx_ones(randperm(numel(idx_ones), flips)); %// Indices of elements
letterA(idx_flips) = 0;                                 %// Flip elements

This will flip 5% of the 1's to 0's.

Upvotes: 2

Shankar Kumar
Shankar Kumar

Reputation: 2357

Thanks for throwing out all these ideas, but eventually I came up with this. It will allow me to easily control both letter and background noise, which is what I intend to do. I'm just a novice, so this may not be the most efficient code, but it gets the job done! (I'm not looking for exactly 5%, the naked eye display value is what I'm more worried about.) PLEASE let me know how this can be improved! Thank you.

background_noise_intensity=0.05;
letter_noise_intensity=0.05;

for i=1:numel(letterA)
    if letterA(i)==0
        if rand < background_noise_intensity
            letterA(i)=1;
        end
    elseif letterA(i)==1
        if rand < letter_noise_intensity
            letterA(i)=0;
        end
    end
end

noisy_letters=letterA;

reshaped_noisy_letters=reshape(noisy_letters,37,19)';
imshow(reshaped_noisy_letters);

Upvotes: 0

Andreas H.
Andreas H.

Reputation: 6073

try this:

letterA( letterA == 1 & rand(size(letterA)) <= 0.05 ) = 0;

In fact you could also do

letterA( rand(size(letterA)) <= 0.05 ) = 0;

which sets each element with probability of 5% to zero. The already zero elements are not affected. I think what causes confusion here is that you have to recognize that each element is independently handled from each other. It makes no difference if you do the first or the second version.

You can check it:

 letterA = (rand(1e5,1) < 0.2); N1 = nnz(letterA);
 letterA( rand(size(letterA)) <= 0.05 ) = 0;
 (N1 - nnz(letterA))/N1

which gives values around 0.05, i.e. 5%. And it is not true what EitanT says, that it will flip at maximum 5%. It can be more than 5% or less, but on average it is 5%.

EitanTs version flippes exactly 5%, so which version to select depends on the application. For EitanT version the noise is correlated to the signal (because it is exact), which may or may not be what you want.

Upvotes: 3

Related Questions