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)
-
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– Abid Rahman K2012年11月28日 07:16:52 +00:00Commented Nov 28, 2012 at 7:16
-
Also see Convert Python program to C/C++ code?jww– jww2019年11月21日 13:37:18 +00:00Commented Nov 21, 2019 at 13:37
2 Answers 2
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.
Comments
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.