vendredi 29 mai 2020

Fast method to access random image pixels and just once

I'm learning OpenCV (C++) and as a simple practice, I designed a simple effect which makes some of image pixels black or white. I want each pixel to be edited only once; so I added address of all pixels to a vector. But it made my code very slow; specially for large images or high amounts of effect. Here is my code:

void effect1(Mat& img, float amount)    // 0 ≥ amount ≥ 100
{
    vector<uchar*> addresses;
    int channels = img.channels();
    uchar* lastAddress = img.ptr<uchar>(0) + img.total() * channels;
    for (uchar* i = img.ptr<uchar>(0); i < lastAddress; i += channels) addresses.push_back(i);   //Fast Enough
    size_t count = img.total() * amount / 100 / 2;
    for (size_t i = 0; i < count; i++)
    {
        size_t addressIndex = xor128() % addresses.size();   //Fast Enough
        for (size_t j = 0; j < channels; j++)
        {
            *(addresses[addressIndex] + j) = 255;
        }   //Fast Enough
        addresses.erase(addresses.begin() + addressIndex);    // MAKES CODE EXTREMELY SLOW
    }
    for (size_t i = 0; i < count; i++)
    {
        size_t addressIndex = xor128() % addresses.size();   //Fast Enough
        for (size_t j = 0; j < channels; j++)
        {
            *(addresses[addressIndex] + j) = 0;
        }   //Fast Enough
        addresses.erase(addresses.begin() + addressIndex);    // MAKES CODE EXTREMELY SLOW
    }
}

I think rearranging vector items after erasing an item is what makes my code slow (if I remove addresses.erase, code will run fast).

Is there any fast method to select each random item from a collection (or a number range) only once?

Also: I'm pretty sure such effect already exists. Does anyone know the name of it?




Aucun commentaire:

Enregistrer un commentaire