Amazing-Ren

导航

例子:Camera Color Picker Sample (YCbCr->ARGB)

本例演示了如何从相机preview缓冲区获取YCbCr模块,并且转化为ARGB。

 

1. 什么是YCbCr

  • y:像素的亮度。以范围从 0 到 255 的字节值形式返回(亮度值始终为正值)。

  • cr:像素的红色色差(色差)。以有符号值的形式返回,范围从 -128 到 127 的整数值。

  • cb:像素的蓝色色差(色差)。以有符号值的形式返回,范围从 -128 到 127 的整数值。

常见的3 个基本色彩模型是RGB,CMYKYUV

YCbCr是YUV压缩和偏移的版本,但是Cb,Cr 同样都指色彩,只是在表示方法上不同而已。在YUV 家族中,YCbCr 是在计算机系统中应用最多的成员,其应用领域很广泛,JPEGMPEG均采用此格式。

YCbCr是DVD、摄像机、数字电视等消费类视频产品中,常用的色彩编码方案。YCbCr 有时会称为 YCC.。Y'CbCr 在模拟分量视频(analog component video)中也常被称为 YPbPr。YCbCr不是一种绝对色彩空间,是YUV压缩和偏移的版本。

 

2. YCbCr与RGB的相互转换

主要的采样格式有: YCbCr 4:2:0、YCbCr 4:2:2、YCbCr 4:1:1和 YCbCr 4:4:4。其中YCbCr 4:1:1 比较常用,其含义为:每个点保存一个 8bit 的亮度值(也就是Y值),每 2x2 个点保存一个 Cr 和Cb 值,图像在肉眼中的感觉不会起太大的变化。所以,原来用 RGB(R,G,B 都是 8bit unsigned) 模型,每个点需要 8x3=24 bits(如下图第一个图). 而现在仅需要 8+(8/4)+(8/4)=12bites,平均每个点占12bites。这样就把图像数据压缩了一半。

 

YCbCr与RGB的相互转换
Y=0.299R+0.587G+0.114B
Cb=0.564(B-Y)
Cr=0.713(R-Y)
-------------------------------------------------------------
R=Y+1.402Cr
G=Y-0.344Cb-0.714Cr
B=Y+1.772Cb

 

 

3. WP中相机获取相机缓冲区

WP中,您可以采用编程方式访问设备相机。除了拍摄照片之外,您还可以访问相机预览缓冲区以实时处理相机帧。PhotoCamera 类的GetPreviewBuffer 方法采用两种格式(ARGB 和 YCbCr)提供相机预览缓冲区中的帧。ARGB 是用于描述应用程序 UI 中颜色的格式。YCbCr 启用高效的图形处理,但不能由 Silverlight 使用。如果您想在您的应用程序中操作某个 YCbCr 帧,则需要将该帧转换为 ARGB,然后该帧才能显示。

详细见:

http://technet.microsoft.com/zh-cn/subscriptions/hh394035

 

 

 代码分析:

1. Rectangle由一个VideoBrush填充。

            <Rectangle.Fill>
                <VideoBrush x:Name="viewfinderBrush">
                    <VideoBrush.RelativeTransform>
                        <RotateTransform CenterX="0.5" CenterY="0.5" x:Name="viewfinderBrushTransformation" />
                    </VideoBrush.RelativeTransform>
                </VideoBrush>
            </Rectangle.Fill>

VideoBrush 是一种类似于 LinearGradientBrushImageBrush 对象的 Brush 对象,可以用来填充Fill或者设置ForeGround,BackGround。

 

2. 为VideoBrush设置Srouce

                cam = new PhotoCamera();
                cam.Initialized += new EventHandler<CameraOperationCompletedEventArgs>(cam_Initialized);
                viewfinderBrush.SetSource(cam);


3. 在后台线程中处理 相机预览缓冲区的 Frame

            if (cam != null)
            {
                Dispatcher.BeginInvoke(delegate()
                {
                    // Set the orientation of the viewfinder.
                    viewfinderBrushTransformation.Angle = cam.Orientation;
                });

                // Start the background worker thread that processes the camera preview buffer frames.
                bgPleaseExit = false;
                bgThread = new Thread(colorConversionBackgroundWorker);
                bgThread.Start();
            }

 

4. colorConversionBackgroundWorker函数 实现

        private void colorConversionBackgroundWorker()
        {
            // Grouping the property change notifications in a batch.
            List<PropertyChangedEventArgs> changeCache = new List<PropertyChangedEventArgs>();
            changeCache.Add(new PropertyChangedEventArgs("CbText"));
            /*
            // For binding from the color plane label.
            public string CbText
            {
                get { return string.Format("Cb = {0}", Cb); }
            }
             
            <TextBlock Canvas.Left="16" Canvas.Top="114" Text="{Binding CbText}" />
            */
            changeCache.Add(new PropertyChangedEventArgs("CrText"));
            changeCache.Add(new PropertyChangedEventArgs("CrOffset"));
            changeCache.Add(new PropertyChangedEventArgs("CbOffset"));
            changeCache.Add(new PropertyChangedEventArgs("YOffset"));
            changeCache.Add(new PropertyChangedEventArgs("ArgbText"));
            changeCache.Add(new PropertyChangedEventArgs("ArgbBrush"));

            // 获取相机YCbCr的像素布局. 它包含了cr, cb等offset, pitch等信息
            var bufferLayout = cam.YCbCrPixelLayout;

            // 获取容纳YCbCr的一帧的缓冲区大小
            byte[] currentPreviewBuffer = new byte[bufferLayout.RequiredBufferSize];

            // 循环获取相机缓冲区
            while (!bgPleaseExit)
            {
                // 取得当前相机的帧的YCbCr数据
                cam.GetPreviewBufferYCbCr(currentPreviewBuffer);

                // The output parameters used in the following method.
                byte y;
                int cr;
                int cb;

                // 从bufferLayout中获取 Y,Cb,Cr的值
                // This location is estimated to be X=320, Y=240. Adjust as desired.
                GetYCbCrFromPixel(bufferLayout, currentPreviewBuffer, 320, 240, out y, out cr, out cb);

                // Set page-level properties to the new YCbCr values.
                Y = y;
                Cb = cb;
                Cr = cr;

                Dispatcher.BeginInvoke(delegate()
                {
                    // not threadsafe, but unlikely to be a problem in this case

                    // Consolidating change notifications
                    if (PropertyChanged != null)
                    {
                        foreach (var change in changeCache)
                            PropertyChanged(this, change);
                    }
                });
            }
        }

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted on 2013-08-15 11:29  Amazing-Ren  阅读(464)  评论(0编辑  收藏  举报