RGB2HSV <-> HSV2RGB 'V' channel issue. (Bug #2451)


Added by Gilad Kapelushnik over 12 years ago. Updated over 12 years ago.


Status:Cancelled Start date:2012-10-16
Priority:Normal Due date:
Assignee:Vadim Pisarevsky % Done:

0%

Category:imgproc, video
Target version:-
Affected version: Operating System:
Difficulty: HW Platform:
Pull request:

Description

Hi,

I'm trying to increase the brightness in an image by converting the image to HSV space, multiplying the V value by a factor and convert the image back to RGB.

I tried to do this and I didn't get correct results. I'm using Emgu but that is just for the invoke function, the code in C should be very similar.

Using version 2.4.2 (under Emgu).

Here is the code:


Emgu.CV.Image<Hsv, float> hsvImage = new Emgu.CV.Image<Hsv, float>(Im.Size);
Emgu.CV.CvInvoke.cvCvtColor(Im.Ptr, hsvImage.Ptr, Emgu.CV.CvEnum.COLOR_CONVERSION.CV_RGB2HSV);
float[, ,] data = hsvImage.Data;

for (int y = 0; y < hsvImage.Height; y++)
{
    for (int x = 0; x < hsvImage.Width; x++)
    {                        
       data[y, x, 2] *= 1.5f; // 2 for V
    }
}

Emgu.CV.Image<Rgb, float> final = new Emgu.CV.Image<Rgb, float>(Im.Size);
Emgu.CV.CvInvoke.cvCvtColor(hsvImage.Ptr, final.Ptr, Emgu.CV.CvEnum.COLOR_CONVERSION.CV_HSV2RGB);

I expect to get a much brighter image...
While manipulating the hue channel and saturation channel produces correct results, changing the value channel doesn't.

I tried to simulate this on matlab and the method is correct (the results I get in matlab are different from the ones under OpenCV):

clear all; close all; clc;

IM = imread('D:\Temp\TestImage.jpg');
IM_hsv = rgb2hsv(IM);
IM_hsv(:,:,3) = IM_hsv(:,:,3) .* 1.5;
IM_new = hsv2rgb(IM_hsv);

figure;
hold on;
imshow(IM);
figure;
imshow(IM_new);

I'll try to dig deeper to figure out what is wrong. If this was already changed/fixed I'll be happy to know.

Gilad.


lena_changed.jpg (110.1 kB) Vadim Pisarevsky, 2012-10-16 09:05 pm


Associated revisions

Revision 3cb49eac
Added by Andrey Pavlenko about 11 years ago

Merge pull request #2451 from ilya-lavrenov:tapi_fast_covar_data

History

Updated by Vadim Pisarevsky over 12 years ago

works for me. Here is the sample code in Python:

import cv2 as cv

a = cv.imread('/Users/vp/work/opencv/samples/c/lena.jpg', 1)
a = a.astype('float32')*(1./255) # bring R, G, B value range to 0..1
hsv = cv.cvtColor(a, cv.COLOR_RGB2HSV)
hsv_planes = cv.split(hsv)
hsv_planes[2] *= 1.5
hsv = cv.merge(hsv_planes)
cv.imshow('lena original', a)
cv.imshow('lena changed', cv.cvtColor(hsv, cv.COLOR_HSV2RGB))
cv.waitKey()
  • Status changed from Open to Cancelled

Updated by Vadim Pisarevsky over 12 years ago

here is the output picture (lena_changed.jpg)

Note that we do not support Emgu wrappers. I just verified that I get reasonable results on my machine. May be, the problem is that after producing the output image, you should make sure that R, G, B are within 0..255 range.

Updated by Gilad Kapelushnik over 12 years ago

Vadim, you are my hero !!!

The problem was in the conversation from a float image to a byte image. some values were above 255.0 (306.0) so the conversation looks for the max value and min value in the float and does a 'linear fitting' to 0-255. I assumed that it was just a simple cast and values above 255 are converted to 255 or just some type of overflow.

Assuming my float image are of values from 0.0 - 100.0, is there a way to convert a float image to a byte image where the byte values are also from 0 - 100?

Thanks again for your help, I spent the whole day on this.

Also available in: Atom PDF