Как оптимизировать эту обработку изображения заменить все пиксели на изображении с ближайшим доступным RGB? - PullRequest
1 голос
/ 13 февраля 2012

Я пытаюсь заменить все пиксели входного изображения ближайшим доступным RGB.У меня есть массив, содержащий цвет и входное изображение.Вот мой код, он дает мне выходное изображение, как и ожидалось, НО это займет очень много времени (около минуты) для обработки одного изображения.Кто-нибудь может помочь мне улучшить код?Или, если у вас есть другие предложения, пожалуйста, помогите.

 UIGraphicsBeginImageContextWithOptions(CGSizeMake(CGImageGetWidth(sourceImage),CGImageGetHeight(sourceImage)), NO, 0.0f);
 //Context size I keep as same as original input image size

 //Otherwise, the output will be only a partial image
 CGContextRef context; 
 context = UIGraphicsGetCurrentContext();

 //This is for flipping up sidedown
 CGContextTranslateCTM(context, 0, self.imageViewArea.image.size.height);
 CGContextScaleCTM(context, 1.0, -1.0);



        // init vars
        float d   = 0;                           // squared error
        int idx = 0;                             // index of palette color
        int min = 1000000;                       // min difference
        UIColor *oneRGB;                         // color at a pixel
        UIColor *paletteRGB;                     // palette color



        // visit each output color and determine closest color from palette
        for(int y=0; y<sizeY; y++) {
            for(int x=0; x<sizeX; x++) {
                // desired (avg) color is one pixel of scaled image
                oneRGB = [inputImgAvg colorAtPixel:CGPointMake(x,y)];


                // find closest color match in palette: init idx with index
                // of closest match; keep track of min to find idx
                min = 1000000;
                idx = 0;

                CGContextDrawImage(context,CGRectMake(xx, yy, 1, 1),img);
            }
        }

        UIImage *output = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        self.imageViewArea.image = output;

Ответы [ 2 ]

1 голос
/ 13 февраля 2012

Обычный ответ - использовать дерево kd или какую-либо другую структуру Octree , чтобы уменьшить количество вычислений и сравнений, которые должны выполняться для каждого пикселя.

Мне также удалось разделить цветовое пространство на регулярную сетку и сохранить список возможных ближайших совпадений для каждой части сетки.Например, вы можете разделить (0-255) значения R, G, B на 16 и получить сетку из (16,16,16) или 4096 элементов в целом.В лучшем случае, для определенного элемента сетки существует только один элемент списка, и нет необходимости вообще обходить список.

1 голос
/ 13 февраля 2012

Это аналогичный вопрос (без однозначного ответа), но в нем есть код для прямого доступа к пикселям из изображения.

Квантование изображения, сохранение списка оставшихся цветов

Вы должны сделать это, а не использовать функции CG для каждого пикселя get и set.Рисование 1 пикселя изображения на другом изображении намного медленнее, чем изменение 3 байтов в массиве.

Кроме того, что в ColorDiff - вам не нужно идеальное различие, если у ближайшего пикселя наименьшийразн.Может быть место для предварительной обработки этого списка, так что для каждой записи палитры у вас будет наименьшее различие с ближайшей другой записью палитры.Затем, просматривая пиксели, я могу быстро проверить, находится ли следующий пиксель в пределах половины этого расстояния от только что найденного цвета (поскольку фотографии, как правило, имеют общие цвета рядом друг с другом).

Если это не совпадает, то при циклическом проходе по палитре, если я нахожусь в пределах половины этого расстояния от какой-либо записи, нет необходимости проверять дальше.

По сути, это помещает зонувокруг каждой записи палитры, где вы точно знаете, что эта является ближайшей.

...