C# 从yuv 420转换为图像<;Bgr,字节>;
我有yuv420数据的字节数组C# 从yuv 420转换为图像<;Bgr,字节>;,c#,emgucv,C#,Emgucv,我有yuv420数据的字节数组 byte[] yuv420;//yuv data 如何将其转换为图像 我找到了一个数学公式,可以转换成RGB,然后再转换成图像,但速度非常慢。有没有办法把它转换得更快 Emgu中有一个用于转换的类 COLOR_CONVERSION(enum CV_YUV2RGB Convert YUV color to RGB) 但是我不明白如何使用这个类。有人能帮忙吗 static Bitmap ConvertYUV2RGB(byte[] yuvFrame, byte
byte[] yuv420;//yuv data
如何将其转换为图像
我找到了一个数学公式,可以转换成RGB,然后再转换成图像,但速度非常慢。有没有办法把它转换得更快
Emgu中有一个用于转换的类
COLOR_CONVERSION(enum CV_YUV2RGB Convert YUV color to RGB)
但是我不明白如何使用这个类。有人能帮忙吗
static Bitmap ConvertYUV2RGB(byte[] yuvFrame, byte[] rgbFrame, int width, int height)
{
int uIndex = width * height;
int vIndex = uIndex + ((width * height) >> 2);
int gIndex = width * height;
int bIndex = gIndex * 2;
int temp = 0;
//图片为pic1,RGB颜色的二进制数据转换得的int r,g,b;
Bitmap bm = new Bitmap(width, height);
int r = 0;
int g = 0;
int b = 0;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
// R分量
temp = (int)(yuvFrame[y * width + x] + (yuvFrame[vIndex + (y / 2) * (width / 2) + x / 2] - 128) * YUV2RGB_CONVERT_MATRIX[0, 2]);
rgbFrame[y * width + x] = (byte)(temp < 0 ? 0 : (temp > 255 ? 255 : temp));
// G分量
temp = (int)(yuvFrame[y * width + x] + (yuvFrame[uIndex + (y / 2) * (width / 2) + x / 2] - 128) * YUV2RGB_CONVERT_MATRIX[1, 1] + (yuvFrame[vIndex + (y / 2) * (width / 2) + x / 2] - 128) * YUV2RGB_CONVERT_MATRIX[1, 2]);
rgbFrame[gIndex + y * width + x] = (byte)(temp < 0 ? 0 : (temp > 255 ? 255 : temp));
// B分量
temp = (int)(yuvFrame[y * width + x] + (yuvFrame[uIndex + (y / 2) * (width / 2) + x / 2] - 128) * YUV2RGB_CONVERT_MATRIX[2, 1]);
rgbFrame[bIndex + y * width + x] = (byte)(temp < 0 ? 0 : (temp > 255 ? 255 : temp));
Color c = Color.FromArgb(rgbFrame[y * width + x], rgbFrame[gIndex + y * width + x], rgbFrame[bIndex + y * width + x]);
bm.SetPixel(x, y, c);
}
}
return bm;
}
static double[,] YUV2RGB_CONVERT_MATRIX = new double[3, 3] { { 1, 0, 1.4022 }, { 1, -0.3456, -0.7145 }, { 1, 1.771, 0 } };
static byte clamp(float input)
{
if (input < 0) input = 0;
if (input > 255) input = 255;
return (byte)Math.Abs(input);
}
静态位图转换器yuv2rgb(字节[]yuvFrame,字节[]rgbFrame,int-width,int-height)
{
int uIndex=宽度*高度;
int-vIndex=uIndex+((宽度*高度)>>2);
int gIndex=宽度*高度;
int bIndex=gIndex*2;
内部温度=0;
//图片为图1,RGB颜色的二进制数据转换得的int r,g,b;
位图bm=新位图(宽度、高度);
int r=0;
int g=0;
int b=0;
对于(int y=0;y255?255:temp));
//G分量
temp=(int)(yuvFrame[y*width+x]+(yuvFrame[uIndex+(y/2)*(width/2)+x/2]-128)*YUV2RGB\u转换矩阵[1,1]+(yuvFrame[vIndex+(y/2)*(width/2)+x/2]-128)*YUV2RGB\u转换矩阵[1,2]);
RGB帧[gIndex+y*宽度+x]=(字节)(温度<0?0:(温度>255?255:temp));
//B分量
temp=(int)(yuvFrame[y*width+x]+(yuvFrame[uIndex+(y/2)*(width/2)+x/2]-128)*YUV2RGB\u CONVERT\u矩阵[2,1]);
rgbFrame[bIndex+y*宽度+x]=(字节)(温度<0?0:(温度>255?255:temp));
颜色c=颜色。来自argb(rgbFrame[y*宽度+x],rgbFrame[gIndex+y*宽度+x],rgbFrame[bIndex+y*宽度+x]);
bm.SetPixel(x,y,c);
}
}
返回bm;
}
静态双精度[,]YUV2RGB_CONVERT__矩阵=新双精度[3,3]{{1,0,1.4022},{1,-0.3456,-0.7145},{1,1.771,0};
静态字节钳位(浮点输入)
{
如果(输入<0)输入=0;
如果(输入>255)输入=255;
返回(字节)Math.Abs(输入);
}
该代码中最大的违规行为是使用Bitmap.SetPixel
;在每个内部循环迭代中执行此操作非常缓慢。相反,使用字节数组存储RGB值,填充后将其复制到位图中
其次,了解y、u和v是字节,因此只能有256个可能的值。因此,为r、g和b构建查找表是完全可行的,因此您不必在内部循环中执行任何计算
最后,如果你真的想要性能,你必须用指针算法在C++中编写,并用所有的优化编译。这个循环也是一个非常好的候选循环,因为每个迭代都在独立的数据上运行。还可以通过对每条指令转换几个像素来进一步优化此功能
希望这能让你开始。你很幸运,因为我以前解决过这个问题。代码中有一些链接可获取更多信息 通常,在进行图像处理时,请始终尝试使用指针,并避免在嵌套循环中调用函数。在我的代码中,大小比较是最慢的部分,但不幸的是它是必需的(请尝试使用预处理器开关将其关闭) 我不得不说,最后我从来没有使用过这个函数,因为它太慢了,我选择用C++实现它,用P调用调用它。p>
private static unsafe void YUV2RGBManaged(byte[] YUVData, byte[] RGBData, int width, int height)
{
//returned pixel format is 2yuv - i.e. luminance, y, is represented for every pixel and the u and v are alternated
//like this (where Cb = u , Cr = y)
//Y0 Cb Y1 Cr Y2 Cb Y3
/*http://msdn.microsoft.com/en-us/library/ms893078.aspx
*
* C = Y - 16
D = U - 128
E = V - 128
R = clip(( 298 * C + 409 * E + 128) >> 8)
G = clip(( 298 * C - 100 * D - 208 * E + 128) >> 8)
B = clip(( 298 * C + 516 * D + 128) >> 8)
* here are a whole bunch more formats for doing this...
* http://stackoverflow.com/questions/3943779/converting-to-yuv-ycbcr-colour-space-many-versions
*/
fixed(byte* pRGBs = RGBData, pYUVs = YUVData)
{
for (int r = 0; r < height; r++)
{
byte* pRGB = pRGBs + r * width * 3;
byte* pYUV = pYUVs + r * width * 2;
//process two pixels at a time
for (int c = 0; c < width; c += 2)
{
int C1 = pYUV[1] - 16;
int C2 = pYUV[3] - 16;
int D = pYUV[2] - 128;
int E = pYUV[0] - 128;
int R1 = (298 * C1 + 409 * E + 128) >> 8;
int G1 = (298 * C1 - 100 * D - 208 * E + 128) >> 8;
int B1 = (298 * C1 + 516 * D + 128) >> 8;
int R2 = (298 * C2 + 409 * E + 128) >> 8;
int G2 = (298 * C2 - 100 * D - 208 * E + 128) >> 8;
int B2 = (298 * C2 + 516 * D + 128) >> 8;
#if true
//check for overflow
//unsurprisingly this takes the bulk of the time.
pRGB[0] = (byte)(R1 < 0 ? 0 : R1 > 255 ? 255 : R1);
pRGB[1] = (byte)(G1 < 0 ? 0 : G1 > 255 ? 255 : G1);
pRGB[2] = (byte)(B1 < 0 ? 0 : B1 > 255 ? 255 : B1);
pRGB[3] = (byte)(R2 < 0 ? 0 : R2 > 255 ? 255 : R2);
pRGB[4] = (byte)(G2 < 0 ? 0 : G2 > 255 ? 255 : G2);
pRGB[5] = (byte)(B2 < 0 ? 0 : B2 > 255 ? 255 : B2);
#else
pRGB[0] = (byte)(R1);
pRGB[1] = (byte)(G1);
pRGB[2] = (byte)(B1);
pRGB[3] = (byte)(R2);
pRGB[4] = (byte)(G2);
pRGB[5] = (byte)(B2);
#endif
pRGB += 6;
pYUV += 4;
}
}
}
}
私有静态不安全无效YUV2RGB管理(字节[]YUVData,字节[]RGBData,整型宽度,整型高度)
{
//返回的像素格式为2yuv-即亮度y表示每个像素,u和v交替
//这样(Cb=u,Cr=y)
//Y0炭黑Y1铬Y2炭黑Y3
/*http://msdn.microsoft.com/en-us/library/ms893078.aspx
*
*C=Y-16
D=U-128
E=V-128
R=夹子((298*C+409*E+128)>>8)
G=夹子((298*C-100*D-208*E+128)>>8)
B=夹子((298*C+516*D+128)>>8)
*这里有更多的格式来做这件事。。。
* http://stackoverflow.com/questions/3943779/converting-to-yuv-ycbcr-colour-space-many-versions
*/
固定(字节*pRGBs=RGBData,pYUVs=YUVData)
{
对于(int r=0;r>8;
INTG1=(298*C1-100*D-208*E+128)>>8;
INTB1=(298*C1+516*D+128)>>8;
int R2=(298*C2+409*E+128)>>8;
int G2=(298*C2-100*D-208*E+128)>>8;
INTB2=(298*C2+516*D+128)>>8;
#如果是真的
//检查是否溢出
//毫不奇怪,这占用了大部分时间。
pRGB[0]=(字节)(R1<0?0:R1>255?255:R1);
pRGB[1]=(字节)(G1<0?0:G1>255?255:G1);
pRGB[2]=(字节)(B1<0?0:B1>255?255:B1);
pRGB[3]=(字节)(R2<0?0:R2>255?255:R2);
pRGB[4]=(字节)(G2<0?0:G2>255?255:G2);
pRGB[5]=(字节)(B2<0?0:B2>255?255:B2);
#否则
pRGB[0]=(字节)(R1);
pRGB[1]=(字节)
void YUV2RGB(void *yuvDataIn,void *rgbDataOut, int w, int h, int outNCh)
{
const int ch2 = 2 * outNCh;
unsigned char* pRGBs = (unsigned char*)rgbDataOut;
unsigned char* pYUVs = (unsigned char*)yuvDataIn;
for (int r = 0; r < h; r++)
{
unsigned char* pRGB = pRGBs + r * w * outNCh;
unsigned char* pYUV = pYUVs + r * w * 2;
//process two pixels at a time
for (int c = 0; c < w; c += 2)
{
int C1 = pYUV[1] - 16;
int C2 = pYUV[3] - 16;
int D = pYUV[2] - 128;
int E = pYUV[0] - 128;
int R1 = (298 * C1 + 409 * E + 128) >> 8;
int G1 = (298 * C1 - 100 * D - 208 * E + 128) >> 8;
int B1 = (298 * C1 + 516 * D + 128) >> 8;
int R2 = (298 * C2 + 409 * E + 128) >> 8;
int G2 = (298 * C2 - 100 * D - 208 * E + 128) >> 8;
int B2 = (298 * C2 + 516 * D + 128) >> 8;
//unsurprisingly this takes the bulk of the time.
pRGB[0] = (unsigned char)(R1 < 0 ? 0 : R1 > 255 ? 255 : R1);
pRGB[1] = (unsigned char)(G1 < 0 ? 0 : G1 > 255 ? 255 : G1);
pRGB[2] = (unsigned char)(B1 < 0 ? 0 : B1 > 255 ? 255 : B1);
pRGB[3] = (unsigned char)(R2 < 0 ? 0 : R2 > 255 ? 255 : R2);
pRGB[4] = (unsigned char)(G2 < 0 ? 0 : G2 > 255 ? 255 : G2);
pRGB[5] = (unsigned char)(B2 < 0 ? 0 : B2 > 255 ? 255 : B2);
pRGB += ch2;
pYUV += 4;
}
}
}
IplImage yuvImage = new IplImage(w, h, BitDepth.U8, 3);
IplImage rgbImage = new IplImage(w, h, BitDepth.U8, 3);
Cv.CvtColor(yuvImage, rgbImage, ColorConversion.CrCbToBgr);
int w= 100;
int h = 200;
int ch = 3;
byte[] imageData = new byte[w*h*ch]; //you image data here
Bitmap bitmap = new Bitmap(w,h,PixelFormat.Format24bppRgb);
BitmapData bmData = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat);
IntPtr pNative = bmData.Scan0;
Marshal.Copy(imageData,0,pNative,w*h*ch);
bitmap.UnlockBits(bmData);
private static unsafe void YUV2RGBManaged(byte[] YUVData, byte[] RGBData, int width, int height)
{
//returned pixel format is 2yuv - i.e. luminance, y, is represented for every pixel and the u and v are alternated
//like this (where Cb = u , Cr = y)
//Y0 Cb Y1 Cr Y2 Cb Y3
/*http://msdn.microsoft.com/en-us/library/ms893078.aspx
*
C = 298 * (Y - 16) + 128
D = U - 128
E = V - 128
R = clip(( C + 409 * E) >> 8)
G = clip(( C - 100 * D - 208 * E) >> 8)
B = clip(( C + 516 * D ) >> 8)
* here are a whole bunch more formats for doing this...
* http://stackoverflow.com/questions/3943779/converting-to-yuv-ycbcr-colour-space-many-versions
*/
fixed(byte* pRGBs = RGBData, pYUVs = YUVData)
{
for (int r = 0; r < height; r++)
{
byte* pRGB = pRGBs + r * width * 3;
byte* pYUV = pYUVs + r * width * 2;
//process two pixels at a time
for (int c = 0; c < width; c += 2)
{
int C1 = 298 * (pYUV[1] - 16) + 128;
int C2 = 298 * (pYUV[3] - 16) + 128;
int D = pYUV[2] - 128;
int E = pYUV[0] - 128;
int R1 = (C1 + 409 * E) >> 8;
int G1 = (C1 - 100 * D - 208 * E) >> 8;
int B1 = (C1 + 516 * D) >> 8;
int R2 = (C2 + 409 * E) >> 8;
int G2 = (C2 - 100 * D - 208 * E) >> 8;
int B2 = (298 * C2 + 516 * D) >> 8;
//check for overflow
//unsurprisingly this takes the bulk of the time.
pRGB[0] = (byte)(R1 < 0 ? 0 : R1 > 255 ? 255 : R1);
pRGB[1] = (byte)(G1 < 0 ? 0 : G1 > 255 ? 255 : G1);
pRGB[2] = (byte)(B1 < 0 ? 0 : B1 > 255 ? 255 : B1);
pRGB[3] = (byte)(R2 < 0 ? 0 : R2 > 255 ? 255 : R2);
pRGB[4] = (byte)(G2 < 0 ? 0 : G2 > 255 ? 255 : G2);
pRGB[5] = (byte)(B2 < 0 ? 0 : B2 > 255 ? 255 : B2);
pRGB += 6;
pYUV += 4;
}
}
}
}