Monday, April 13, 2015

การประมวลผลภาพวิดีโอจาก Kinect ตัวอย่างการสร้างภาพกลับสี (Negative)

เมื่อเราอ่านค่าวิดีโอจาก Kinect มาเก็บในตัวแปรชุด หรืออาร์เรย์ (Array) เพื่อจะไปสร้างเป็นบิตแมพ  ขณะที่เก็บข้อมูลในอาร์เรย์ เราสามารถปรับเปลี่ยนหรือแก้ไขข้อมูลพิกเซลของภาพได้

โครงสร้างการเก็บข้อมูลพิกเซล ที่เราได้มาจาก Kinect ด้วยคำสั่ง colorFrame.CopyPixelDataTo(colorData); นั้น จะเป็นข้อมูลแบบไบต์ (byte) ที่เก็บในอาร์เรย์หนึ่งมิติ โดยหนึ่งพิกเซลจะประกอบไปด้วยอาร์เรย์สี่ช่อง แบบ BGRA นั่นคือ
0-Blue
1-Green
2-Red
3-Alpha
โดยเลข 0,1,2,... เป็น index ของอาร์เรย์ และวนไปเรื่อยๆ คือ 4-Blue, 5-Green, 6-Red, 7-Alpha...


แต่ละช่องสีก็จะถูกเก็บด้วยตัวแปรชนิดไบต์ นั่นคือ 1 ช่องสี = 1 byte = 8 bits และเก็บค่าช่วงสีได้ 2^8 = 256 ค่า (0-255) ดังนั้น หนึ่งพิกเซลจะใช้อาร์เรย์ 4 ช่อง = 4 bytes = 32 bits

ในที่นี้ เราจะลองมาเปลี่ยนค่าสีของพิกเซล โดยสร้างภาพกลับสี (Negative) กันครับ หลักการคือถ้าอ่านค่าสีพิกเซลได้เท่าใด ให้นำไปหักออกจาก 255 ก็จะได้ค่าสีที่อยู่ตรงข้ามครับ

สมมติว่ารูปปกติคือ

ตัวอย่างผลลัพธ์ที่ได้ก็จะเป็น

การแก้ไขก็จะแก้เฉพาะส่วนของ byte array ก่อนที่จะสร้างบิตแมพ ซึ่งจะแก้ในเฉพาะส่วนของฟังก์ชันที่เป็นผลของ ColorFrameReady ดังนี้ครับ

สังเกตว่าส่วนที่แก้ไขมีนิดเดียว อยู่ระหว่าเส้นประที่ขีดไว้ครับ
        void myKinect_ColorFrameReady(object sender, ColorImageFrameReadyEventArgs e)
        {
            using (ColorImageFrame colorFrame = e.OpenColorImageFrame())
            {
                //if get new video frame
                if (colorFrame == null)
                    return;
                //create an array of pixel data
                if(colorData==null)
                    colorData = new byte[colorFrame.PixelDataLength];
                //extract pixel data from the frame to the array
                colorFrame.CopyPixelDataTo(colorData);

                //------------------------------------------------------
                //modify the pixel data
                //0=Blue,1=Green,2=Red,3=Alpha
                for (int i = 0; i < colorData.Length; i = i + 4)
                {
                    //image negative
                    //blue
                    colorData[i] = (byte)(255 - colorData[i]);
                    //green
                    colorData[i + 1] = (byte)(255 - colorData[i + 1]);
                    //red
                    colorData[i + 2] = (byte)(255 - colorData[i + 2]);
                }
                //------------------------------------------------------

                //For the first video frame, no bitmap, create a writable bitmap of video size
                if (imageBitmap == null)
                {
                    imageBitmap = new WriteableBitmap(
                        colorFrame.Width,
                        colorFrame.Height,
                        96,     //dpiX
                        96,     //dpiY
                        PixelFormats.Bgr32,
                        null    //palette:none
                        );
                }
                //For other video frames, write video data to bitmap
                imageBitmap.WritePixels(
                    new Int32Rect(0, 0, colorFrame.Width, colorFrame.Height),
                    colorData,  //video data
                    colorFrame.Width * colorFrame.BytesPerPixel,      //stride
                    0   //offset to the array
                    );
                //set bitmap to image view
                kinectVideo.Source = imageBitmap;
            }
        }

No comments:

Post a Comment