2017-02-08 19 views
3

Я хочу реализовать smth-подобную кривую тона.OpenCV Tone Curve progrommatically

У меня есть предопределенный набор кривых, которые я должен применить к изображению. Например: enter image description here

, как я понимаю, на этом графике мы видим зависимости текущего значения тона на новые, например: , если мы получим первую точку слева - каждый г, г и Ь, что = 0 будет преобразуется в 64 или каждое значение более 224 будет преобразовано в 0 и ect.

поэтому я попытался изменить каждый пиксель изображения на новое значение

для целей тестирования я упростил кривой:

enter image description here

и здесь код у меня есть:

//init original image 
cv::Mat originalMat = [self cvMatFromUIImage:inputImage]; 

//out image the same size 
cv::Mat outMat  = [self cvMatFromUIImage:inputImage]; 

//loop throw every row of image 
for(int y = 0; y < originalMat.rows; y++){ 
    //loop throw every column of image 
    for(int x = 0; x < originalMat.cols; x++){ 
    //loop throw every color channel of image (R,G,B) 
    for(int c = 0; c < 3; c++){ 

     if(originalMat.at<cv::Vec3b>(y,x)[c] <= 64) 
     outMat.at<cv::Vec3b>(y,x)[c] = 64 + (originalMat.at<cv::Vec3b>(y,x)[c]) - 
     (originalMat.at<cv::Vec3b>(y,x)[c]) * 2 ; 

     if((originalMat.at<cv::Vec3b>(y,x)[c] > 64)&&(originalMat.at<cv::Vec3b>(y,x)[c] <= 128)) 
     outMat.at<cv::Vec3b>(y,x)[c] = ((originalMat.at<cv::Vec3b>(y,x)[c]) - 64 ) * 4 
     ; 

     if((originalMat.at<cv::Vec3b>(y,x)[c] > 128)) 
     outMat.at<cv::Vec3b>(y,x)[c] = (originalMat.at<cv::Vec3b>(y,x)[c]) + 128 - 
     ((originalMat.at<cv::Vec3b>(y,x)[c]) - 128) * 3; 

    } //end of r,g,b loop 
    } //end of column loop 
} //end of row loop 

//send to output 
return [self UIImageFromCVMat:outMat]; 

, но здесь я получаю: enter image description here

по какой-то причине только 3/4 изображения был обработан

и не совпадения с результатом я ожидаемому: enter image description here

Update 0

благодаря @ACCurrent комментарий обнаружены ошибки в вычислении (обновлены код и изображение), но до сих пор не понятно, почему обрабатывается только 3/4 изображений.

не уверен, что поймите, почему появляется «шум», надеюсь, что из-за кривой негладкой.

выглядит так, чтобы избежать .at операции.

Update 1

исходное изображение:

enter image description here

+1

Избегайте использования opencv '.при функции <> 'это очень медленно. Также при первой проверке допустим значение на 'gaussMat.at (y, x) [c]' = 128 Затем: 'if ((gaussMat.at (y, x) [c]> 64) && (gaussMat.at (y, x) [c] <= 128)) outMat.at (y, x) [c] = (gaussMat.at (y, x) [c]) - 64 + (gaussMat.at (y, x) [c]) * 4' Таким образом, 128-64 + 128 * 4 равно 576, что превышает 255 максимальное значение для CV_U8c. Поэтому будет насыщенность. – ACCurrent

+1

Вы также можете опубликовать исходное изображение? И не волнуйтесь ... функция 'at' не медленная. Вы можете использовать его без каких-либо проблем. – Miki

+0

@Miki исходное изображение добавлено – user5599807

ответ

3

Вы должны получить доступ к образам с Vec4b


originalMat.typ е() является равна 24

Ваш originalMat имеет тип 24, т.е. CV_8UC4. Это означает, что изображение имеет 4 канала, но вы обращаетесь к нему с Vec3b, как будто он имеет только 3 канала. Это объясняет, почему около 1/4 изображения не изменяется.

Итак, просто замените каждый Vec3b в своем коде Vec4b.