注:在阴影检测算法中经常需要将RGB格式的图像转化为HSV格式,对于阴影区域而言,它的色度和饱和度相对于原图像而言变化不大,主要是亮度信息变化较大,,将RGB格式转化为HSV格式,就可以得到H、S、V分量,从而得到色度、饱和度、亮度得值;
转换程序:
void convert_ImageRGBtoHSV(const Mat& imageRGB, Mat &imageHSV)
{
float fR, fG, fB;
float fH, fS, fV;
const float FLOAT_TO_BYTE = 255.0f;
const float BYTE_TO_FLOAT = 1.0f / FLOAT_TO_BYTE;
// Create a blank HSV image
//if (!imageHSV || imageRGB->depth != 8 || imageRGB->nChannels != 3) {
//printf("ERROR in convertImageRGBtoHSV()! Bad input image.\n");
//exit(1);
//}
int h = imageRGB.rows; // Pixel height.
int w = imageRGB.cols; // Pixel width.
//int rowSizeRGB = imageRGB->widthStep; // Size of row in bytes, including extra padding.
//char *imRGB = imageRGB->imageData; // Pointer to the start of the image pixels.
//int rowSizeHSV = imageHSV->widthStep; // Size of row in bytes, including extra padding.
//char *imHSV = imageHSV->imageData; // Pointer to the start of the image pixels.
for (int y = 0; y < h; ++y) {
for (int x = 0; x < w; ++x) {
// Get the RGB pixel components. NOTE that OpenCV stores RGB pixels in B,G,R order.
//uchar *pRGB = (uchar*)(imRGB + y*rowSizeRGB + x*3);
int bB = imageRGB.at<Vec3b>(y, x)[0]; //*(uchar*)(pRGB+0); // Blue component
int bG = imageRGB.at<Vec3b>(y, x)[1]; //*(uchar*)(pRGB+1); // Green component
int bR = imageRGB.at<Vec3b>(y, x)[2]; //*(uchar*)(pRGB+2); // Red component
// Convert from 8-bit integers to floats.
fR = bR * BYTE_TO_FLOAT;
fG = bG * BYTE_TO_FLOAT;
fB = bB * BYTE_TO_FLOAT;
// Convert from RGB to HSV, using float ranges 0.0 to 1.0.
float fDelta;
float fMin, fMax;
int iMax;
// Get the min and max, but use integer comparisons for slight speedup.
if (bB < bG) {
if (bB < bR) {
fMin = fB;
if (bR > bG) {
iMax = bR;
fMax = fR;
}
else {
iMax = bG;
fMax = fG;
}
}
else {
fMin = fR;
fMax = fG;
iMax = bG;
}
}
else {
if (bG < bR) {
fMin = fG;
if (bB > bR) {
fMax = fB;
iMax = bB;
}
else {
fMax = fR;
iMax = bR;
}
}
else {
fMin = fR;
fMax = fB;
iMax = bB;
}
}
fDelta = fMax - fMin;
fV = fMax; // Value (Brightness).
if (iMax != 0) { // Make sure its not pure black.
fS = fDelta / fMax; // Saturation.
float ANGLE_TO_UNIT = 1.0f / (6.0f * fDelta); // Make the Hues between 0.0 to 1.0 instead of 6.0
if (iMax == bR) { // between yellow and magenta.
fH = (fG - fB) * ANGLE_TO_UNIT;
}
else if (iMax == bG) { // between cyan and yellow.
fH = (2.0f / 6.0f) + (fB - fR) * ANGLE_TO_UNIT;
}
else { // between magenta and cyan.
fH = (4.0f / 6.0f) + (fR - fG) * ANGLE_TO_UNIT;
}
// Wrap outlier Hues around the circle.
if (fH < 0.0f)
fH += 1.0f;
if (fH >= 1.0f)
fH -= 1.0f;
}
else {
// color is pure Black.
fS = 0;
fH = 0; // undefined hue
}
// Convert from floats to 8-bit integers.
int bH = (int)(0.5f + fH * 255.0f);
int bS = (int)(0.5f + fS * 255.0f);
int bV = (int)(0.5f + fV * 255.0f);
// Clip the values to make sure it fits within the 8bits.
if (bH > 255)
bH = 255;
if (bH < 0)
bH = 0;
if (bS > 255)
bS = 255;
if (bS < 0)
bS = 0;
if (bV > 255)
bV = 255;
if (bV < 0)
bV = 0;
// Set the HSV pixel components.
imageHSV.at<Vec3b>(y, x)[0] = bH; // H component
imageHSV.at<Vec3b>(y, x)[1] = bS; // S component
imageHSV.at<Vec3b>(y, x)[2] = bV; // V component
}
}
}