[英]Pixels in YUV image
我正在使用opencv來實現對象跟蹤。 我讀到YUV圖像比RGB圖像更好。 我的問題是,盡管我花很多時間閱讀筆記,但仍無法理解YUV格式。 Y是我認為是根據R,G,B成分的組合計算得出的亮度。
我的主要問題是如何訪問和操縱YUV圖像格式的像素。 在RGB格式中,它易於訪問組件,因此可以使用簡單的操作如
src.at<Vec3b>(j,i).val[0] = 0; for example
但這不是YUV中的情況。 在訪問和更改YUV圖像中的像素值時,我需要幫助。 例如,如果RGB中的像素為紅色,那么我只想將相應的像素保留在YUV中,其余的將被刪除。 請幫我解決一下這個。
我建議您在HSV或LAB中而不是RGB上對圖像進行操作。
來自相機的原始圖像將保存在YCbCr中(有時稱為YUV,我認為這是不正確的,但我可能是錯的),其布局方式類似於YUYV(重復),因此,如果您可以直接從對於HSV,您將避免進行額外的復制和轉換操作,從而節省了一些時間。 但是,這僅對您很重要,如果您正在處理視頻或成批圖像。
這是一些在YCbCr和RGB之間轉換的C ++代碼(一個使用整數數學,另一個使用浮點數):
Colour::bgr Colour::YCbCr::toBgrInt() const
{
int c0 = 22987;
int c1 = -11698;
int c2 = -5636;
int c3 = 29049;
int y = this->y;
int cb = this->cb - 128;
int cr = this->cr - 128;
int b = y + (((c3 * cb) + (1 << 13)) >> 14);
int g = y + (((c2 * cb + c1 * cr) + (1 << 13)) >> 14);
int r = y + (((c0 * cr) + (1 << 13)) >> 14);
if (r < 0)
r = 0;
else if (r > 255)
r = 255;
if (g < 0)
g = 0;
else if (g > 255)
g = 255;
if (b < 0)
b = 0;
else if (b > 255)
b = 255;
return Colour::bgr(b, g, r);
}
Colour::bgr Colour::YCbCr::toBgrFloat() const
{
float y = this->y;
float cb = this->cb;
float cr = this->cr;
int r = y + 1.40200 * (cr - 0x80);
int g = y - 0.34414 * (cb - 0x80) - 0.71414 * (cr - 0x80);
int b = y + 1.77200 * (cb - 0x80);
if (r < 0)
r = 0;
else if (r > 255)
r = 255;
if (g < 0)
g = 0;
else if (g > 255)
g = 255;
if (b < 0)
b = 0;
else if (b > 255)
b = 255;
return Colour::bgr(b, g, r);
}
從BGR轉換為HSV:
Colour::hsv Colour::bgr2hsv(bgr const& in)
{
Colour::hsv out;
int const hstep = 255 / 3; // Hue step size between red -> green -> blue
int min = in.r < in.g ? in.r : in.g;
min = min < in.b ? min : in.b;
int max = in.r > in.g ? in.r : in.g;
max = max > in.b ? max : in.b;
out.v = max; // v
int chroma = max - min;
if (max > 0)
{
out.s = 255 * chroma / max; // s
}
else
{
// r = g = b = 0 // s = 0, v is undefined
out.s = 0;
out.h = 0;
out.v = 0; // it's now undefined
return out;
}
if (chroma == 0)
{
out.h = 0;
return out;
}
const int chroma2 = chroma * 2;
int offset;
int diff;
if (in.r == max)
{
offset = 3 * hstep;
diff = in.g - in.b;
}
else if (in.g == max)
{
offset = hstep;
diff = in.b - in.r;
}
else
{
offset = 2 * hstep;
diff = in.r - in.g;
}
int h = offset + (diff * (hstep + 1)) / chroma2;
// Rotate such that red has hue 0
if (h >= 255)
h -= 255;
assert(h >= 0 && h < 256);
out.h = h;
return out;
不幸的是,我沒有一步就能做到的代碼。
您也可以使用內置的OpenCV函數進行顏色轉換 。
cvtColor(img, img, CV_BGR2HSV);
U和V分量也被計算為RGB值的線性組合。 然后,這意味着將不同強度的紅色(R,0,0)映射到某個強度(y * R + a,u * R + b,v * R + c),這再次意味着檢測到YUV可以計算由y,u,v,a,b,c(其中有些是多余的)確定的像素到該行的距離是否接近零。 使用單點積是可以實現的。 然后將剩余像素設置為YUV空間中的(0,128,128)(我認為在幾乎所有的YCrCb,YUV等品種中R = 0,G = 0,B = 0)。
YUV格式有幾種,但是常見的格式使Y保持與原始圖像相同的分辨率,但是U和V為一半大小,並在單通道Y圖像緩沖區之后保存為單獨的或隔行的平面/通道。
這使您可以有效地將Y作為1通道8位灰度圖像進行訪問。
訪問和操作像素不知道顏色格式,因此相同的代碼適用於顏色分量YU和V。如果需要在RGB模式下訪問,最好的方法是cv::cvtColor
針對您感興趣的區域調用cv::cvtColor
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.