Пример #1
0
        private static List <Rect> GetBelowHorizontalFlagRect(Rect belowFlgRect, Bitmap image)
        {
            List <Rect> result = new List <Rect>();
            Rect        rect;

            bool[,] marker = new bool[image.Width, image.Height];
            int   y            = belowFlgRect.GetCenterPoint().y;
            int   x            = belowFlgRect.GetCenterPoint().x;
            int   totalFlgRect = Constant.BELOW_HORIZONTAL_FLAG_RECT;
            Point p;

            while (result.Count < totalFlgRect)
            {
                p = new Point(x, y);
                if (!p.IsValidPoint())
                {
                    throw new Exception(ErrorUtils.getError(ErrorUtils.CAN_NOT_GET_ENOUGH_HORIZONTAL_FLAG_RECT, "Can not get enough horizontal flag rect!!"));
                }
                if (!marker[x, y] && CommonImageProcessing.IsBlackColor(new Point(x, y), image))
                {
                    rect = CommonImageProcessing.ExpandTheRectBlackPixel(new Point(x, y), image, ref marker);
                    if (rect == null)
                    {
                        throw new Exception(ErrorUtils.getError(ErrorUtils.CAN_NOT_GET_ENOUGH_HORIZONTAL_FLAG_RECT, "Can not get enough horizontal flag rect!!"));
                    }
                    if (CommonImageProcessing.IsFlagRectangle(rect))
                    {
                        result.Add(rect);
                    }
                }
                x--;
            }
            return(result);
        }
Пример #2
0
        private static Rect DetectBottomRightCorner(Bitmap image)
        {
            var   marker          = new bool[image.Width, image.Height];
            Point p               = CommonImageProcessing.FindDifferentColorPoint(new Point(Constant.AS_RIGHT_BORDER, Constant.AS_BOTTOM_BORDER), image, Constant.WHITE, ref marker);
            Rect  bottomRightRect = CommonImageProcessing.ExpandTheRectBlackPixel(p, image, ref marker);

            if (bottomRightRect == null)
            {
                p = CommonImageProcessing.FindDifferentColorPoint(new Point(Constant.AS_RIGHT_BORDER, Constant.AS_BOTTOM_BORDER), image, Constant.WHITE, ref marker);
                bottomRightRect = CommonImageProcessing.ExpandTheRectBlackPixel(p, image, ref marker);
                if (bottomRightRect == null)
                {
                    throw new Exception(ErrorUtils.getError(ErrorUtils.CAN_NOT_FIND_THE_TOP_RIGHT_FLAG_RECT, "Can not detect the top right flag rectangle. Tried 2 attempts!!"));
                }
                else
                {
                    ValidateBottomRightFlagRect(bottomRightRect);
                    return(bottomRightRect);
                }
            }
            else
            {
                ValidateBottomRightFlagRect(bottomRightRect);
                return(bottomRightRect);
            }
        }
Пример #3
0
        private static Rect DetectTopRightFlagRect(Bitmap image)
        {
            //In case the points expanded not match the template rectangle. We need to mark the visited point, so we don't go to these point again
            var   marker           = new bool[image.Width, image.Height];
            Point p                = CommonImageProcessing.FindDifferentColorPoint(new Point(Constant.AS_RIGHT_BORDER, Constant.AS_TOP_BORDER), image, Constant.WHITE, ref marker);
            Rect  topRightFlagRect = CommonImageProcessing.ExpandTheRectBlackPixel(p, image, ref marker);

            if (topRightFlagRect == null)
            {
                p = CommonImageProcessing.FindDifferentColorPoint(new Point(Constant.AS_RIGHT_BORDER, Constant.AS_TOP_BORDER), image, Constant.WHITE, ref marker);
                topRightFlagRect = CommonImageProcessing.ExpandTheRectBlackPixel(p, image, ref marker);
                if (topRightFlagRect == null)
                {
                    throw new Exception(ErrorUtils.getError(ErrorUtils.CAN_NOT_FIND_THE_TOP_RIGHT_FLAG_RECT, "Can not detect the top right flag rectangle. Tried 2 attempts!!"));
                }
                else
                {
                    ValidateTopRightFlagRect(topRightFlagRect);
                    return(topRightFlagRect);
                }
            }
            else
            {
                ValidateTopRightFlagRect(topRightFlagRect);
                return(topRightFlagRect);
            }
        }
Пример #4
0
        private static List <Rect> GetVerticalFlagRect(Rect aboveFlgRect, Bitmap image)
        {
            List <Rect> result = new List <Rect>();
            Rect        rect;

            bool[,] marker = new bool[image.Width, image.Height];
            int   y            = aboveFlgRect.GetCenterPoint().y;
            int   x            = aboveFlgRect.GetCenterPoint().x;
            int   totalFlgRect = TemplateUtils.GetNumberOfVerticalFLagRect(Globals.currentTemplate);
            Point p;

            while (result.Count < totalFlgRect)
            {
                p = new Point(x, y);
                if (!p.IsValidPoint())
                {
                    throw new Exception(ErrorUtils.getError(ErrorUtils.CAN_NOT_GET_ENOUGH_VERTICAL_FLAG_RECT, "Can not get enough vertical flag rect!!"));
                }
                if (!marker[x, y] && CommonImageProcessing.IsBlackColor(new Point(x, y), image))
                {
                    rect = CommonImageProcessing.ExpandTheRectBlackPixel(new Point(x, y), image, ref marker);
                    if (rect == null)
                    {
                        throw new Exception(ErrorUtils.getError(ErrorUtils.CAN_NOT_GET_ENOUGH_VERTICAL_FLAG_RECT, "Can not get enough vertical flag rect!!"));
                    }
                    if (CommonImageProcessing.IsFlagRectangle(rect))
                    {
                        result.Add(rect);
                    }
                }
                y++;
            }
            return(result);
        }
Пример #5
0
        private static Tuple <String, List <Circle> > DetectExamCode(Bitmap img, List <Rect> horizontalFlgRects, List <Rect> verticalFlgRects)
        {
            string        examId     = "";
            List <Circle> lstCircles = new List <Circle>();
            Circle        c;
            bool          found;

            for (int i = 1; i < 4; i++)
            {
                found = false;
                for (int j = 1; j < 11; j++)
                {
                    Rect  r1 = horizontalFlgRects[i];
                    Rect  r2 = verticalFlgRects[j];
                    Point c1 = r1.GetCenterPoint();
                    Point c2 = r2.GetCenterPoint();
                    c = new Circle(new Point(c1.x, c2.y), Constant.DEFAULT_CIRCLE_RADIUS);
                    int nOfBlackInCircle = CommonImageProcessing.CountNumberOfBlackPixelInCircle(img, c, -5);
                    if (nOfBlackInCircle >= Constant.NUMBER_OF_CIRCLE_BLACK_PIXEL_TO_BE_CONSIDERED_INFO_AS_CHOOSEN)
                    {
                        if (found)
                        {
                            examId = "-";
                        }
                        else
                        {
                            found = true;
                            if (examId != "-")
                            {
                                examId = (j - 1).ToString() + examId;
                            }
                        }
                        lstCircles.Add(c);
                    }
                }
                if (!found)
                {
                    examId = examId + "*";
                }
            }
            return(new Tuple <string, List <Circle> >(examId, lstCircles));
        }
Пример #6
0
        private static Bitmap PreProcess(Bitmap img)
        {
            i++;
            //img.Save(@"D:\hello.jpg");
            img = CommonImageProcessing.SmoothImage(img);
            //img.Save(@"D:\hello_smooth.jpg");
            img = CommonImageProcessing.ConvertToBinary(img);
            img.Save(@"D:\hello_smooth_black1.jpg");
            Rect   topRightRect    = DetectTopRightFlagRect(img);
            Rect   bottomRightRect = DetectBottomRightCorner(img);
            double angle           = calculateRotateAngle(topRightRect, bottomRightRect);

            if (Math.Abs(topRightRect.bottomRight.x - bottomRightRect.bottomRight.x) > Constant.ACCEPTABLE_DIFF_BETWEEN_TOP_RIGHT_FLG_RECT_AND_BOTTOM_RIGHT_FLG_RECT)
            {
                img = CommonImageProcessing.RotateImage(img, angle - 90);
            }
            img.Save(@"D:\" + i + ".jpg");

            return(img);
        }
Пример #7
0
        public static ProcessedAS ProcessAS(Bitmap img)
        {
            if (img.Width != Constant.AS_WIDTH || img.Height != Constant.AS_HEIGHT)
            {
                img = CommonImageProcessing.ResizeImage(img, Constant.AS_WIDTH, Constant.AS_HEIGHT);
            }
            Bitmap orgImg = img;

            img = PreProcess(img);

            Rect topRightRect    = DetectTopRightFlagRect(img);
            Rect bottomRightRect = DetectBottomRightCorner(img);

            List <Rect> verticalFlagRects        = GetVerticalFlagRect(topRightRect, img);
            List <Rect> aboveHorizontalFlagRects = GetAboveHorizontalFlagRect(topRightRect, img);
            List <Rect> belowHorizontalFlagRects = GetBelowHorizontalFlagRect(bottomRightRect, img);

            Tuple <String, List <Circle> > studentCodeResult = DetectStudentCode(img, belowHorizontalFlagRects, verticalFlagRects);
            Tuple <String, List <Circle> > examCodeResult    = DetectExamCode(img, belowHorizontalFlagRects, verticalFlagRects);
            Tuple <List <Char>, List <Circle>, List <Point> > studentAnswersResult = DetectStudentAnswer(img, aboveHorizontalFlagRects, verticalFlagRects);

            String examId    = examCodeResult.Item1;
            String studentId = studentCodeResult.Item1;

            ProcessedAS processedAS = new ProcessedAS();

            processedAS.examId    = examId;
            processedAS.studentId = studentId;

            StudentAnswer studentAnswer;

            int numberOfQuestion = Globals.numberOfQuestion;

            List <Char>  answerText = studentAnswersResult.Item1;
            List <Point> positions  = studentAnswersResult.Item3;

            List <StudentAnswer> studentAnswers = new List <StudentAnswer>();

            for (int i = 1; i <= numberOfQuestion; i++)
            {
                Point p = positions[i];
                // 300 x 38
                // CvInvoke.Rectangle(outputImg, rect, new MCvScalar(255, 0, 255), 2);
                studentAnswer = new StudentAnswer(answerText[i], new Point(p.x - 45, p.y - 18));
                studentAnswers.Add(studentAnswer);
            }

            processedAS.answers = studentAnswers;

            //List<Circle> tmp;
            //tmp = studentCodeResult.Item2;
            //Image<Bgr, Byte> outputImg = new Image<Bgr, Byte>(img);
            //foreach (Circle circle in tmp)
            //{
            //    CvInvoke.Circle(outputImg, new System.Drawing.Point(circle.center.x, circle.center.y), circle.radius - 2, new MCvScalar(0, 255, 0), 2);
            //}

            //tmp = examCodeResult.Item2;

            //foreach (Circle circle in tmp)
            //{
            //    CvInvoke.Circle(outputImg, new System.Drawing.Point(circle.center.x, circle.center.y), circle.radius - 2, new MCvScalar(0, 255, 0), 2);
            //}

            //tmp = studentAnswersResult.Item2;

            //foreach (Circle circle in tmp)
            //{
            //    CvInvoke.Circle(outputImg, new System.Drawing.Point(circle.center.x, circle.center.y), circle.radius-2, new MCvScalar(0, 255, 0), 2);
            //}

            processedAS.processedAnswerSheetImage = orgImg;

            return(processedAS);
        }
Пример #8
0
        private static Tuple <List <Char>, List <Circle>, List <Point> > DetectStudentAnswer(Bitmap img, List <Rect> horizontalFlgRects, List <Rect> verticalFlgRects)
        {
            int numberOfQuestion = Globals.numberOfQuestion;

            List <Char>   answers      = new List <Char>();
            List <Circle> lstCircles   = new List <Circle>();
            List <Point>  borderPoints = new List <Point>();

            for (int i = 0; i < numberOfQuestion + 1; i++)
            {
                answers.Add('*');
                borderPoints.Add(new Point(-100, -100));
            }

            int nHorizontalRect = horizontalFlgRects.Count;
            int nVerticalRect   = verticalFlgRects.Count;

            Char   currentAns = 'A';
            int    currentQuestion;
            int    colStartQuestion = 1;
            int    numberOfRow      = (nVerticalRect - 12);
            Circle c;

            for (int i = nHorizontalRect - 1; i >= 1; i--)
            {
                currentQuestion = colStartQuestion;
                for (int j = 11; j < nVerticalRect - 1; j++)
                {
                    if (currentQuestion > numberOfQuestion)
                    {
                        break;
                    }
                    Rect  r1 = horizontalFlgRects[i];
                    Rect  r2 = verticalFlgRects[j];
                    Point c1 = r1.GetCenterPoint();
                    Point c2 = r2.GetCenterPoint();
                    if (currentAns == 'A')
                    {
                        borderPoints[currentQuestion] = new Point(c1.x, c2.y);
                    }
                    c = new Circle(new Point(c1.x, c2.y), Constant.DEFAULT_CIRCLE_RADIUS);
                    int nOfBlackInCircle = CommonImageProcessing.CountNumberOfBlackPixelInCircle(img, c, 8);
                    if (nOfBlackInCircle >= Constant.NUMBER_OF_CIRCLE_BLACK_PIXEL_TO_BE_CONSIDERED_ANSWER_AS_CHOOSEN)
                    {
                        if (answers[currentQuestion] == '*')
                        {
                            answers[currentQuestion] = currentAns;
                        }
                        else
                        {
                            answers[currentQuestion] = '-';
                        }
                        lstCircles.Add(c);
                    }
                    currentQuestion++;
                    if (currentQuestion > numberOfQuestion)
                    {
                        break;
                    }
                }
                if (currentAns == 'E')
                {
                    currentAns        = 'A';
                    colStartQuestion += numberOfRow;
                }
                else
                {
                    currentAns++;
                }
            }
            return(new Tuple <List <char>, List <Circle>, List <Point> >(answers, lstCircles, borderPoints));
        }