Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DetectRectangle using OpenCV #8

Merged
merged 12 commits into from
Sep 12, 2022
Merged

DetectRectangle using OpenCV #8

merged 12 commits into from
Sep 12, 2022

Conversation

Juhwa-Lee1023
Copy link
Owner

@Juhwa-Lee1023 Juhwa-Lee1023 commented Sep 12, 2022

@LeeSungNo-ian
@jeong-hyeonHwang

Outline

Work Contents

  • detectRectangle

Trouble Point

1. detectRectangle

  • �Trouble Situation

    • In the case of detectRectangle using visionKit, the Sudoku area is not well recognized.`('visionKit'을 이용한 'detectRectangle'의 경우 스도쿠영역 인식이 잘 되지않는다.)
      무제
      Commit : 92ac192
  • Trouble Shooting

    • Tried detectRectangle using OpenCV('OpenCV'를 이용하여 'detectRectangle'를 시도했다.)

image

// grayScale을 입힌다.
cv::Mat toGray;
cv::cvtColor(mat, toGray, CV_BGR2GRAY);

image

// threshold를 강조한다.
cv::Mat toThresh;
cv::adaptiveThreshold(toGray, toThresh, 255, CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY_INV, 31, 31);

image

// 테두리를 찾는다.
std::vector<std::vector<cv::Point>> contours;
std::vector<cv::Vec4i> hierarchy;
cv::findContours(toThresh, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);

image

        // 제일 큰 테두리를 찾는다.
        double maxArea = 0;
        int maxContourIndex = 0;
        for (int i = 0; i < contours.size(); i++)
        {
            double area = cv::contourArea(contours[i]);
            if (area > maxArea)
            {
                maxArea = area;
                maxContourIndex = i;
            }
        }
        std::vector<cv::Point> maxContour = contours[maxContourIndex];

        // 제일 큰 테두리에서 사각형을 찾는다.
        std::vector<int> sumv, diffv;
        for (int i = 0; i < maxContour.size(); i++)
        {
            cv::Point p = maxContour[i];
            sumv.push_back(p.x + p.y);
            diffv.push_back(p.x - p.y);
        }
        // c++의 distance를 이용해 테두리의 각 모서리를 찾는다.
        auto mins = std::distance(std::begin(sumv), std::min_element(std::begin(sumv), std::end(sumv)));
        auto maxs = std::distance(std::begin(sumv), std::max_element(std::begin(sumv), std::end(sumv)));
        auto mind = std::distance(std::begin(diffv), std::min_element(std::begin(diffv), std::end(diffv)));
        auto maxd = std::distance(std::begin(diffv), std::max_element(std::begin(diffv), std::end(diffv)));
        std::vector<cv::Point> maxRect;
        maxRect.push_back(maxContour[mins]); // 왼쪽 위 모서리
        maxRect.push_back(maxContour[mind]); // 오른쪽 위 모서리
        maxRect.push_back(maxContour[maxs]); // 오른쪽 아래 모서리
        maxRect.push_back(maxContour[maxd]); // 왼쪽 아래 모서리
        
        // 구한 모서리를 이용해 각 모서리의 좌표를 구한다.
        cv::Point tl = maxRect[0];
        cv::Point tr = maxRect[1];
        cv::Point br = maxRect[2];
        cv::Point bl = maxRect[3];
        // 좌표간에 거리를 계산한뒤 제곱하고 루트를 씌워 모서리 사이의 거리(변의 길이)를 구한다.
        double widthA = sqrt(pow((br.x - bl.x), 2) + pow((br.y - bl.y), 2));
        double widthB = sqrt(pow((tr.x - tl.x), 2) + pow((tr.y - tl.y), 2));
        double heightA = sqrt(pow((tr.x - br.x), 2) + pow((tr.y - br.y), 2));
        double heightB = sqrt(pow((tl.x - bl.x), 2) + pow((tl.y - bl.y), 2));
        // 평행하는 변 중 긴 변을 구한다.
        double maxWidth = fmax(int(widthA), int(widthB));
        double maxHeight = fmax(int(heightA), int(heightB));

        // 구한 긴 변을 기준으로 짧은 변을 늘린다.
        cv::Point2f dst[4] =
        {
            cv::Point2f(0, 0),
            cv::Point2f(maxWidth, 0),
            cv::Point2f(maxWidth, maxHeight),
            cv::Point2f(0, maxHeight)
        };
        cv::Point2f src[4] = { tl, bl, br, tr };
        cv::Mat M = cv::getPerspectiveTransform(src, dst);
        cv::Mat warpMat;
        cv::warpPerspective(mat, warpMat, M, cv::Size(maxWidth, maxHeight));

        NSMutableArray *result = [[NSMutableArray alloc] init];
        [result addObject:pointToArray(maxRect)];
        [result addObject:MatToUIImage(warpMat)];
        
        return result;
    }
    @catch (...)
    {
        return nil;
    }
}

1

@Juhwa-Lee1023 Juhwa-Lee1023 self-assigned this Sep 12, 2022
@Juhwa-Lee1023 Juhwa-Lee1023 linked an issue Sep 12, 2022 that may be closed by this pull request
1 task
Copy link

@jeong-hyeonHwang jeong-hyeonHwang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

다른 언어를 랩핑해서 쓸 수 있다는게 신기하네요! 👍👍👍

Sudoku/wrapper.mm Outdated Show resolved Hide resolved
Sudoku/wrapper.mm Show resolved Hide resolved
@Juhwa-Lee1023 Juhwa-Lee1023 merged commit 9dd8328 into main Sep 12, 2022
@Juhwa-Lee1023 Juhwa-Lee1023 deleted the 7-feat-detectrectangle branch September 12, 2022 16:07
@Juhwa-Lee1023 Juhwa-Lee1023 added the enhancement New feature or request label Sep 12, 2022
@LeeSungNo-ian
Copy link

OpenCV 를 Swift 에 접목하시다니 ㅎㄷㄷ.. 이번 PR은 제가 리뷰하는게 힘들 것 같군요🥲
OpenCV 리뷰를 드릴 수 있을 때 까지 열심히 공부하겠습니다!

이안 화이팅!

Copy link

@yeniful yeniful left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

objc-c 코드...!! 어렵지만 차근차근 꼼꼼히 읽어보려고 노력을 했어요! Objective C++ 흥미롭네요 ㅎㅎ

Sudoku/wrapper.mm Show resolved Hide resolved
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

feat: detectRectangle
4 participants