簡體   English   中英

YUV圖像中的像素

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM