ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 앵커찾기 (With OpenCV)
    c# Winform 개발/UI 2021. 6. 21. 09:31

     

    마우스로 클릭할때 OpenCV로 그린오브젝트(네모,폴리곤)에 포함되는지 확인하고할 때 썼었다.

     

    OpenCVOjbect  = 그려진 오브젝트(네모,폴리곤).

     

    각 꼭지점은 앵커라고 부르며 앵커의 경우 BLK로 조금 더 진하게 보이도록 UI에서 변경한 다음

     

    마우스 클릭 이벤트에서 아래 함수를 호출하도록 해서 사용함. 

     

    ex)

    TL = Top Left

    TM = Top Middle

    TR = Top Right

    BL = Bottom Left

    ...

     

    public class Constant
        {
            public const int ANCHOR_LOC_TL = 1;
            public const int ANCHOR_LOC_TM = 2;
            public const int ANCHOR_LOC_TR = 3;
            public const int ANCHOR_LOC_LM = 4;
            public const int ANCHOR_LOC_RM = 5;
            public const int ANCHOR_LOC_BL = 6;
            public const int ANCHOR_LOC_BM = 7;
            public const int ANCHOR_LOC_BR = 8;
            
            public const int BLK = 4;
        }

     

    #region 네모 앵커 찾기
            public bool pointInBoundRectangle(int x, int y, OpenCVOjbect dragObj)
            {
                bool isFind = false;
                if (pointInRect(x, y, dragObj.outRect.X - Constant.BLK, dragObj.outRect.Y - Constant.BLK, Constant.BLK * 4, Constant.BLK * 4))
                {
                    dragObj.selectRectangleAnchor = Constant.ANCHOR_LOC_TL;
                    isFind = true;
                }
                // endif
                if (pointInRect(x, y, dragObj.outRect.X + dragObj.outRect.Width - Constant.BLK, dragObj.outRect.Y - Constant.BLK, Constant.BLK * 4, Constant.BLK * 4))
                {
                    dragObj.selectRectangleAnchor = Constant.ANCHOR_LOC_TR;
                    isFind = true;
                }
                // endif
                if (pointInRect(x, y, dragObj.outRect.X - Constant.BLK, dragObj.outRect.Y + dragObj.outRect.Height - Constant.BLK, Constant.BLK * 4, Constant.BLK * 4))
                {
                    dragObj.selectRectangleAnchor = Constant.ANCHOR_LOC_BL;
                    isFind = true;
                }
                // endif
                if (pointInRect(x, y, dragObj.outRect.X + dragObj.outRect.Width - Constant.BLK, dragObj.outRect.Y + dragObj.outRect.Height - Constant.BLK, Constant.BLK * 4, Constant.BLK * 4))
                {
                    dragObj.selectRectangleAnchor = Constant.ANCHOR_LOC_BR;
                    isFind = true;
                }
                // endif
                if (pointInRect(x, y, dragObj.outRect.X + dragObj.outRect.Width / 2 - Constant.BLK, dragObj.outRect.Y - Constant.BLK, Constant.BLK * 4, Constant.BLK * 4))
                {
                    dragObj.selectRectangleAnchor = Constant.ANCHOR_LOC_TM;
                    isFind = true;
                }
                // endif
                if (pointInRect(x, y, dragObj.outRect.X + dragObj.outRect.Width / 2 - Constant.BLK, dragObj.outRect.Y + dragObj.outRect.Height - Constant.BLK, Constant.BLK * 4, Constant.BLK * 4))
                {
                    dragObj.selectRectangleAnchor = Constant.ANCHOR_LOC_BM;
                    isFind = true;
                }
                // endif
                if (pointInRect(x, y, dragObj.outRect.X - Constant.BLK, dragObj.outRect.Y + dragObj.outRect.Height / 2 - Constant.BLK, Constant.BLK * 4, Constant.BLK * 4))
                {
                    dragObj.selectRectangleAnchor = Constant.ANCHOR_LOC_LM;
                    isFind = true;
                }
                // endif
                if (pointInRect(x, y, dragObj.outRect.X + dragObj.outRect.Width - Constant.BLK, dragObj.outRect.Y + dragObj.outRect.Height / 2 - Constant.BLK, Constant.BLK * 4, Constant.BLK * 4))
                {
                    dragObj.selectRectangleAnchor = Constant.ANCHOR_LOC_RM;
                    isFind = true;
                }

                return isFind;
            }
            #endregion 네모 앵커 찾기
            #region 네모안에 포함되는지 찾기
            // 주의 : rx,ry,rw,rh는 음수가 되면 안됨. 2020.12.28
            public bool pointInRect(
                int pX,
                int pY,
                int rX,
                int rY,
                int rW,
                int rH)
            {
                if (((rX <= pX) && pX <= (rX + rW)) && ((rY <= pY) && pY <= (rY + rH)))
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            #endregion 네모안에 포함되는지 찾기 끝

            #region 폴리곤 안에 포함되는지 찾기
            // Given three colinear points p, q, r, the function checks if 
            // point q lies on line segment 'pr' 
            bool onSegment(OpenCvSharp.Point p, OpenCvSharp.Point q, OpenCvSharp.Point r)
            {

                if (q.X <= Math.Max(p.X, r.X) && q.X >= Math.Min(p.X, r.X) &&
                        q.Y <= Math.Max(p.Y, r.Y) && q.Y >= Math.Min(p.Y, r.Y))
                    return true;
                return false;
            }

            // To find orientation of ordered triplet (p, q, r). 
            // The function returns following values 
            // 0 --> p, q and r are colinear 
            // 1 --> Clockwise 
            // 2 --> Counterclockwise 
            int orientation(OpenCvSharp.Point p, OpenCvSharp.Point q, OpenCvSharp.Point r)
            {
                int val = (q.Y - p.Y) * (r.X - q.X) -
                        (q.X - p.X) * (r.Y - q.Y);

                if (val == 0) return 0; // colinear 
                return (val > 0) ? 1 : 2; // clock or counterclock wise 
            }

            bool doIntersect(OpenCvSharp.Point p1, OpenCvSharp.Point q1, OpenCvSharp.Point p2, OpenCvSharp.Point q2)
            {
                // Find the four orientations needed for general and 
                // special cases 
                int o1 = orientation(p1, q1, p2);
                int o2 = orientation(p1, q1, q2);
                int o3 = orientation(p2, q2, p1);
                int o4 = orientation(p2, q2, q1);

                // General case 
                if (o1 != o2 && o3 != o4)
                    return true;

                // Special Cases 
                // p1, q1 and p2 are colinear and p2 lies on segment p1q1 
                if (o1 == 0 && onSegment(p1, p2, q1)) return true;

                // p1, q1 and p2 are colinear and q2 lies on segment p1q1 
                if (o2 == 0 && onSegment(p1, q2, q1)) return true;

                // p2, q2 and p1 are colinear and p1 lies on segment p2q2 
                if (o3 == 0 && onSegment(p2, p1, q2)) return true;

                // p2, q2 and q1 are colinear and q1 lies on segment p2q2 
                if (o4 == 0 && onSegment(p2, q1, q2)) return true;

                return false; // Doesn't fall in any of the above cases 
            }
            public bool isInside(List<Point> polygon, int n, Point p)
            {
                // There must be at least 3 vertices in polygon[] 
                if (n < 3) return false;

                // Create a point for line segment from p to infinite 
                Point extreme = new Point(Constant.INF, p.Y);

                // Count intersections of the above line with sides of polygon 
                int count = 0, i = 0;
                do
                {
                    int next = (i + 1) % n;

                    // Check if the line segment from 'p' to 'extreme' intersects 
                    // with the line segment from 'polygon[i]' to 'polygon[next]' 
                    if (doIntersect(polygon[i], polygon[next], p, extreme))
                    {
                        // If the point 'p' is colinear with line segment 'i-next', 
                        // then check if it lies on segment. If it lies, return true, 
                        // otherwise false 
                        if (orientation(polygon[i], p, polygon[next]) == 0)
                            return onSegment(polygon[i], p, polygon[next]);

                        count++;
                    }
                    i = next;
                } while (i != 0);

                // Return true if count is odd, false otherwise 
                return (count % 2 == 1);
            }
            #endregion 폴리곤 안에 포함되는지 찾기 끝
            #region 폴리곤 앵커 찾기
            public bool pointInBoundPolygon(int x, int y, OpenCVOjbect dragObj)
            {
                bool isFind = false;
                int polygonidx = 0;
                foreach (Point point in dragObj.polygonPoints)
                {
                    if (pointInRect(x, y, point.X - Constant.BLK*2, point.Y - Constant.BLK*2, Constant.BLK * 4, Constant.BLK * 4))
                    {
                        dragObj.selectPolygonAnchor = polygonidx;
                        
                        isFind = true;
                        break;
                    }
                    polygonidx++;
                }

                return isFind;
            }
            #endregion 폴리곤 앵커 찾기

    300x250

    댓글

Designed by Tistory.