บทความนี้เราจะมาพูดถึงเรื่องการตรวจจับรูปสี่เหลี่ยม (Rectangle Detection) ซึ่งมีความจำเป็นค่อนข้างมากในงานทางด้าน Image processing

Source code:
Image<Bgr, Byte> imgInput = new Image<Bgr, byte>("ที่อยู่รูปภาพ");
CvInvoke.cvShowImage("Input image",imgInput);

Image<Gray, Byte> grayImage = imgInput.Convert<Gray, Byte>();
Image<Gray, Byte> cannyEdges = grayImage.Canny(new Gray(180), new Gray(120));
CvInvoke.cvShowImage("Edge image", cannyEdges);
     
List<MCvBox2D> rectangleList = new List<MCvBox2D>();
MemStorage storage = new MemStorage();
for (Contour<Point> contours = cannyEdges.FindContours(); contours != null; contours = contours.HNext){
        Contour<Point> currentContour = contours.ApproxPoly(contours.Perimeter * 0.05, storage);
        if (contours.Area > 50) {
             if (currentContour.Total == 4) {
                 bool isRectangle = true;
                 Point[] pts = currentContour.ToArray();
                 LineSegment2D[] edges = PointCollection.PolyLine(pts, true);

                 for (int i = 0; i < edges.Length; i++){
                      double angle = Math.Abs(edges[(i + 1) % edges.Length].GetExteriorAngleDegree(edges[i]));

                      if (angle < 80 || angle > 100){
                           isRectangle = false;
                            break;
                      }
                  }

             if (isRectangle){
                  rectangleList.Add(currentContour.GetMinAreaRect());
              }
          }
     }
}
foreach (MCvBox2D box in rectangleList){
     imgInput.Draw(box, new Bgr(Color.Black), 2);
}
CvInvoke.cvShowImage("Draw rectangle", imgInput);



Code review: การทำงานของโปรแกรมนี้จะแบ่งออกเป็น  3 ส่วนใหญ่ๆ นะครับ
-           Get Input / show output image
-           Canny edge detection
-           Rectangle detection

Get input / show output image: ในส่วนนี้มีหน้าที่รับภาพที่ใช้เป็นข้อมูลอินพุต และแสดงภาพเอาต์พุตออกมาครับ
Image<Bgr, Byte> imgInput = new Image<Bgr, byte>("ที่อยู่รูปภาพ");
CvInvoke.cvShowImage("Input image",imgInput);

input image


Canny edge detection: ในขั้นตอนนี้จะแปลงค่าสีจาก RGB เป็น Gray scale และใช้ Method Canny ซึ่งอยู่ในไลบราลี่ emgucv เพื่อหาเส้นขอบในรูปภาพครับ
Image<Gray, Byte> grayImage = imgInput.Convert<Gray, Byte>();
Image<Gray, Byte> cannyEdges = grayImage.Canny(new Gray(180), new Gray(120));
CvInvoke.cvShowImage("Edge image", cannyEdges);

Canny edge detection output


Rectangle detection: ในขั้นตอนนี้เราจะนำภาพที่ได้จากการทำ Canny มาหา contour เงื่อนไขที่ contour ใดๆ จะเป็นรูปสี่เหลี่ยมได้นั้นจะต้องมีครบทั้ง 3 เงื่อนไขดังนี้  1. ต้องมีขนาดมากกว่า 50 px   
                                                          2. มีจำนวนจุดเท่ากับ 4 จุด   
                                                                             3. เส้นแต่ละเส้นจะต้องทำมุมกันอยู่ในช่วง 80-100 องศา
ถ้า contour ใดมีเงื่อนไขครบทั้ง 3 กรณีนี้ถือได้ว่า contour นั้นคือรูปสี่เหลี่ยม

List<MCvBox2D> rectangleList = new List<MCvBox2D>();
MemStorage storage = new MemStorage();
for (Contour<Point> contours = cannyEdges.FindContours(); contours != null; contours = contours.HNext){
          
Contour<Point> currentContour = contours.ApproxPoly(contours.Perimeter * 0.05, storage);
       if (contours.Area > 50) //ตรวจสอบขนาดของ contour ต้องมากกว่า 50
                {
                    if (currentContour.Total == 4) //ตรวจสอบจำนวนจุดของ contour ==  4
                    {
                        bool isRectangle = true;
                        Point[] pts = currentContour.ToArray();
                        LineSegment2D[] edges = PointCollection.PolyLine(pts, true);

                        for (int i = 0; i < edges.Length; i++)
                        {
                            double angle = Math.Abs(edges[(i + 1) % edges.Length].GetExteriorAngleDegree(edges[i]));
                            if (angle < 80 || angle > 100) // ตรวจสอบ องศา
                            {
                                isRectangle = false;
                                break;
                            }
                        }

                        if (isRectangle) //isRectangle == true
                        {
                            rectangleList.Add(currentContour.GetMinAreaRect());
                        }
                    }
                }
            }
            foreach (MCvBox2D box in rectangleList) //วาดกรอบสี่เหลี่ยมรอบๆ วัตถุที่เป็นสี่เหลี่ยม
            {
                imgInput.Draw(box, new Bgr(Color.Black), 2);
            }
            CvInvoke.cvShowImage("Draw rectangle", imgInput);




3 ความคิดเห็น

May 16, 2013 at 8:37 PM

ขอบคุณครับ กำลังศึกษาเรื่องนี้อยู่ ^_^

Reply
June 29, 2015 at 1:38 PM

ขอบคุณค่ะ กำลัง ลองศึกษาเรื่องนี้

Reply
November 10, 2015 at 10:29 PM

please help..
crop rectangle

Reply

Post a Comment

Templated by Blogger Items