1

I found this very nice code from @abid-rahman-k to detect a rectangle from image: OpenCV C++/Obj-C: Advanced square detection Now the code is in Python and here it is:

import cv2
import numpy as np

img = cv2.imread('sof.jpg')
img = cv2.resize(img,(500,500))
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

ret,thresh = cv2.threshold(gray,127,255,0)
contours,hier = cv2.findContours(thresh,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)

for cnt in contours:
    if cv2.contourArea(cnt)>5000:  # remove small areas like noise etc
        hull = cv2.convexHull(cnt)    # find the convex hull of contour
        hull = cv2.approxPolyDP(hull,0.1*cv2.arcLength(hull,True),True)
        if len(hull)==4:
            cv2.drawContours(img,[hull],0,(0,255,0),2)

cv2.imshow('img',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

I would like to convert it into Objective C/ C++. This is what I did, but did not work, what did I miss?

- (void)processImage2:(cv::Mat&)image;
{
    cv::Mat img,gray,thresh;

    std::vector<std::vector<cv::Point> > contours;

    //  cv::resize(image.clone(), image, cv::Size(500,500) );

    cvtColor(image,  gray, cv::COLOR_BGR2GRAY );

    cv::threshold(gray, thresh, 127, 255, 0);
    findContours(thresh, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);


    std::vector<cv::Point> hull;
    for (size_t i = 0; i < contours.size(); i++)
    {
        if (cv::contourArea(contours[i])>5000){
            cv::convexHull(contours[i],hull);
           approxPolyDP(hull, hull, 0.1*arcLength(hull, true), true);
            if (hull.size() ==4)
               cv::drawContours(image,hull,0,cv::Scalar(0,255,0),2);

        }
    }


}

Update:

The program runs but after I select the image it crashes and I get this error:

Nov 28 10:26:52 Anas-Basalamahs-MacBook-Air.local OpenCV Tutorial[18861] <Error>: CGBitmapContextCreate: unsupported parameter combination: 0 integer bits/component; 0 bits/pixel; 0-component color space; kCGImageAlphaNone; 0 bytes/row.
Nov 28 10:26:52 Anas-Basalamahs-MacBook-Air.local OpenCV Tutorial[18861] <Error>: CGContextConcatCTM: invalid context 0x0
Nov 28 10:26:52 Anas-Basalamahs-MacBook-Air.local OpenCV Tutorial[18861] <Error>: CGContextSetInterpolationQuality: invalid context 0x0
Nov 28 10:26:52 Anas-Basalamahs-MacBook-Air.local OpenCV Tutorial[18861] <Error>: CGContextDrawImage: invalid context 0x0
Nov 28 10:26:52 Anas-Basalamahs-MacBook-Air.local OpenCV Tutorial[18861] <Error>: CGBitmapContextCreateImage: invalid context 0x0
2012-11-28 10:26:52.963 OpenCV Tutorial[18861:c07] resized image size: NSSize: {0, 0}
OpenCV Error: Assertion failed (i < 0) in getMat, file /Users/bloodaxe/Develop/opencv/modules/core/src/matrix.cpp, line 957
terminate called throwing an exception(lldb) 
Community
  • 1
  • 1
alandalusi
  • 1,145
  • 4
  • 18
  • 39
  • what do you mean it didn't work? Is result wrong? then upload the result you got. Does your code show any error? then update your answer with error log. – Abid Rahman K Nov 28 '12 at 07:16
  • Also see [Convert Python program to C/C++ code?](https://stackoverflow.com/q/4650243/608639) – jww Nov 21 '19 at 13:37

2 Answers2

1

Here, this is working:

cv::Mat oResult, oToShow;
// roMat is your input image
cv::cvtColor(roMat, oToShow, CV_GRAY2BGR);

cv::threshold(roMat, oResult, 127, 255, 0);
std::vector<std::vector<cv::Point>> contours;
std::vector<cv::Vec4i> hierarchy;

cv::findContours( oResult, contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE );


std::vector<std::vector<cv::Point> > oHull(contours.size());
for( int i = 0; i != contours.size(); i++)
{
    if( cv::contourArea(contours[i]) > 5000 )
    {
        cv::convexHull(contours[i], oHull[i]);
        cv::approxPolyDP(oHull[i], oHull[i], 0.1*cv::arcLength(oHull[i], true), true);
        if( oHull[i].size() == 4 )
        {
            cv::drawContours(oToShow, oHull, -1, cv::Scalar(0, 255,0), 2, 8);
        }

    }
}

cv::imshow("hull", oToShow);
cv::waitKey(0);

I think the error was, that you actually got an Array of Hulls, and not just one Hull.

Hafnernuss
  • 2,659
  • 2
  • 29
  • 41
0

I don't see an imread in your code, so I'm assuming you are reading the image outside this function and passing it in. Have you tried doing an imshow right after reading to ensure the image is correctly loaded.

The first line indicates to me that that could be the problem.