I have stumbled upon an exception in my application that I am unable to get rid of...
I am trying to write a simple image face recognition program with all three face recognition algorithms(Eigen, Fisher and LBPH).
The unchandled exception is caused by line :
Fisher_prediction = Fisher_model->predict(crop);
and theerror message says: Unhandled exception at at 0x000007FEFDB3A49D in FaceRecognition.exe: Microsoft C++ exception: cv::Exception at memory location 0x00000000002782B0.
and is caused by: msvcr110d.dll!_CxxThrowException(void * pExceptionObject, const _s__ThrowInfo * pThrowInfo) Line 152 C++
Any sugestions where am I going wrong??
here is the rest of the code:
Mat frame = imread("1.jpg");
// Apply the classifier to the frame
if (!frame.empty()) {
cvtColor(frame, frame_gray, COLOR_BGR2GRAY);
equalizeHist(frame_gray, frame_gray);
// Detect faces
face_cascade.detectMultiScale(frame_gray, faces, 1.1, 2, 0 | CASCADE_SCALE_IMAGE, Size(30, 30));
// Set Region of Interest
cv::Rect roi_b;
cv::Rect roi_c;
size_t ic = 0; // ic is index of current element
int ac = 0; // ac is area of current element
size_t ib = 0; // ib is index of biggest element
int ab = 0; // ab is area of biggest element
// Iterate through all current elements (detected faces)
for (ic = 0; ic < faces.size(); ic++) {
roi_c.x = faces[ic].x;
roi_c.y = faces[ic].y;
roi_c.width = (faces[ic].width);
roi_c.height = (faces[ic].height);
ac = roi_c.width * roi_c.height; // Get the area of current element (detected face)
roi_b.x = faces[ib].x;
roi_b.y = faces[ib].y;
roi_b.width = (faces[ib].width);
roi_b.height = (faces[ib].height);
ab = roi_b.width * roi_b.height; // Get the area of biggest element, at beginning it is same as "current" element
if (ac > ab) {
ib = ic;
roi_b.x = faces[ib].x;
roi_b.y = faces[ib].y;
roi_b.width = (faces[ib].width);
roi_b.height = (faces[ib].height);
}
crop = frame(roi_b);
cv::resize(crop, res, Size(img_width, img_height), 0, 0, INTER_LINEAR); // This will be needed later while saving images
cvtColor(crop, gray, CV_BGR2GRAY); // Convert cropped image to Grayscale
Point pt1(faces[ic].x, faces[ic].y); // Display detected faces on main window - live stream from camera
Point pt2((faces[ic].x + faces[ic].height), (faces[ic].y + faces[ic].width));
//rectangle(frame, pt1, pt2, Scalar(0, 255, 0), 2, 8, 0);
/* Calculate the position for annotated text */
int pos_x = std::max(roi_b.tl().x - 10, 0);
int pos_y = std::max(roi_b.tl().y - 10, 0);
if(createdFisher) {
Fisher_prediction = Fisher_model->predict(crop);
QString Fisher_qs = QString::number(Fisher_prediction);
/* Create the text we will annotate the box with */
string Fisher_text = format("Prediction Fisherfaces = %d", Fisher_prediction);
putText(frame, Fisher_text, Point(pos_x, pos_y), FONT_HERSHEY_PLAIN, 1.0, CV_RGB(0,255,0), 2.0);
/* Draw a green rectangle around the detected face */
rectangle(frame, pt1, pt2, MATCH_COLOR, 1);
ui.txtConsole->appendPlainText(QString("Fisherfaces - " + Fisher_qs));
}
if(createdEigen) {
Eigen_prediction = Eigen_model->predict(crop);
QString Eigen_qs = QString::number(Eigen_prediction);
/* Create the text we will annotate the box with */
string Eigen_text = format("Prediction Eigenfaces = %d", Eigen_prediction);
putText(frame, Eigen_text, Point(pos_x, pos_y), FONT_HERSHEY_PLAIN, 1.0, CV_RGB(0,255,0), 2.0);
/* Draw a green rectangle around the detected face */
rectangle(frame, pt1, pt2, MATCH_COLOR, 1);
ui.txtConsole->appendPlainText(QString("Eigenfaces - " + Eigen_qs));
}
if(createdLBPH) {
LBPH_prediction = LBPH_model->predict(crop);
QString LBPH_qs = QString::number(LBPH_prediction);
/* Create the text we will annotate the box with */
string LBPH_text = format("Prediction LBPH = %d", LBPH_prediction);
putText(frame, LBPH_text, Point(pos_x, pos_y), FONT_HERSHEY_PLAIN, 1.0, CV_RGB(0,255,0), 2.0);
/* Draw a green rectangle around the detected face */
rectangle(frame, pt1, pt2, MATCH_COLOR, 1);
ui.txtConsole->appendPlainText(QString("Linear Binary Patern Histogram - " + LBPH_qs));
}
}
putText(frame, text, cvPoint(30, 30), FONT_HERSHEY_COMPLEX_SMALL, 0.8, cvScalar(0, 0, 255), 1, CV_AA);
imshow("original", frame);
if (!crop.empty()) {
imshow("detected", crop);
}
else
destroyWindow("detected");
}
int c = waitKey(0);
All the necessary #include and variables along with the classifier are initialised at the start of the program.
What I was doing wrong is that I was passing a picture to the facerecogniser that was not resized (I am using pictures that are 200x200px in my database) , so the algorithm could not do the face recognition based on a larger resolution image than the one that is in a database.
Related
I'm doing object reconstruction from structure from motion. The current situation right now, is I'm getting a multiple views for a car and apply a mask rcnn for that object to remove the background, because I only want that object to reconstruct and have a clean object.
My current issues, right now are that The Object is not fully reconstructured.
The mask that I get from Mask RCNN is not always have a fixed size for the SFM to work
A background noise is still present in the scene reconstructed object
Camera parameters are messed up when I use only the mask that are got from different views, how to fix that ?
Here are some results:
Original image of course there are mutliple views of it
Mask RCNN results that I use for SFM
and here is the result from SFM
// Draw the predicted bounding box, colorize and show the mask on the image
void drawBox(Mat& frame, int classId, float conf, Rect box, Mat& objectMask, std::vector<Mat> &contours_images)
{
//Draw a rectangle displaying the bounding box
//rectangle(frame, Point(box.x, box.y), Point(box.x + box.width, box.y + box.height), Scalar(255, 178, 50), 3);
//Get the label for the class name and its confidence
string label = format("%.2f", conf);
if (!classes.empty())
{
CV_Assert(classId < (int)classes.size());
label = classes[classId] + ":" + label;
}
//Display the label at the top of the bounding box
int baseLine;
Size labelSize = getTextSize(label, FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);
box.y = max(box.y, labelSize.height);
//rectangle(frame, Point(box.x, box.y - round(1.5 * labelSize.height)), Point(box.x + round(1.5 * labelSize.width), box.y + baseLine), Scalar(255, 255, 255), FILLED);
//putText(frame, label, Point(box.x, box.y), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(0, 0, 0), 1);
// Resize the mask, threshold, color and apply it on the image
// Scalar color = colors[classId % colors.size()];
// Resize the mask, threshold, color and apply it on the image
resize(objectMask, objectMask, Size(box.width, box.height));
Mat mask = (objectMask > maskThreshold);
//Mat coloredRoi = (0.3 * color + 0.7 * frame(box));
// coloredRoi.convertTo(coloredRoi, CV_8UC3);
Mat coloredRoi(frame(box));
// Draw the contours on the image
vector<Mat> contours;
Mat hierarchy;
mask.convertTo(mask, CV_8U);
findContours(mask, contours, hierarchy, RETR_CCOMP, cv::CHAIN_APPROX_NONE);
//drawContours(coloredRoi, contours, -1, color, 5, LINE_8, hierarchy, 100);
// coloredRoi.copyTo(frame(box), mask);
Mat outframe;
coloredRoi.copyTo(outframe, mask);
cv::resize(outframe, outframe, cv::Size(400, 400));
contours_images.push_back(outframe);
// imshow("outframe", outframe);
// waitKey(0);
}
// For each frame, extract the bounding box and mask for each detected object
void postprocess(Mat& frame, const vector<Mat>& outs, vector<Mat> & maskes)
{
Mat outDetections = outs[0];
Mat outMasks = outs[1];
// Output size of masks is NxCxHxW where
// N - number of detected boxes
// C - number of classes (excluding background)
// HxW - segmentation shape
const int numDetections = outDetections.size[2];
const int numClasses = outMasks.size[1];
outDetections = outDetections.reshape(1, outDetections.total() / 7);
for (int i = 0; i < numDetections; ++i)
{
float score = outDetections.at<float>(i, 2);
if (score > confThreshold)
{
// Extract the bounding box
int classId = static_cast<int>(outDetections.at<float>(i, 1));
int left = static_cast<int>(frame.cols * outDetections.at<float>(i, 3));
int top = static_cast<int>(frame.rows * outDetections.at<float>(i, 4));
int right = static_cast<int>(frame.cols * outDetections.at<float>(i, 5));
int bottom = static_cast<int>(frame.rows * outDetections.at<float>(i, 6));
left = max(0, min(left, frame.cols - 1));
top = max(0, min(top, frame.rows - 1));
right = max(0, min(right, frame.cols - 1));
bottom = max(0, min(bottom, frame.rows - 1));
Rect box = Rect(left, top, right - left + 1, bottom - top + 1);
// Extract the mask for the object
Mat objectMask(outMasks.size[2], outMasks.size[3], CV_32F, outMasks.ptr<float>(i, classId));
// Draw bounding box, colorize and show the mask on the image
drawBox(frame, classId, score, box, objectMask, maskes);
}
}
}
I'm trying to build a simple Augmented Reality application using OpenCV 4.1.1 and Aruco. The goal is to overlay an image on top of a marker but have the image go beyond the edges of the marker.
I have calibrated my camera and gotten the camera matrix and distortion coefficients. By using OpenCV's warpPerspective I can draw an image on top of a marker, but I can only tie it to the corners of the marker so it stays within the border of the marker.
std::vector<int> ids;
std::vector<std::vector<Point2f>> corners;
// detect markers
aruco::detectMarkers(image, dictionary, corners, ids);
if (ids.size() > 0) {
// file with image to draw
auto file = "square.png";
// image to draw on the marker
Mat im_src = imread(file);
if (im_src.data == NULL) {
std::cout << file << ": File not found\n" << std::endl;
continue;
}
// flip(im_src, im_src, 1);
// points of corners of the image
std::vector<Point2f> pts_src;
pts_src.push_back(Point2f(0, 0));
pts_src.push_back(Point2f(im_src.cols-1, 0));
pts_src.push_back(Point2f(im_src.cols-1, im_src.rows-1));
pts_src.push_back(Point2f(0, im_src.rows-1));
// use aruco marker
for (int i = 0; i < ids.size(); i++) {
if (ids[i] == 69) {
aruco::drawDetectedMarkers(imageCopy, corners, ids);
std::vector<Point> pts_dst;
pts_dst.push_back(corners[i][0]);
pts_dst.push_back(corners[i][1]);
pts_dst.push_back(corners[i][2]);
pts_dst.push_back(corners[i][3]);
Mat h = findHomography(pts_src, pts_dst);
Mat im_out;
warpPerspective(im_src, im_out, h, imageCopy.size());
fillConvexPoly(imageCopy, pts_dst, 0, 16);
imageCopy = imageCopy + im_out;
}
}
Here is an image of what I have and what I want. I think I need to use 3d points to draw the image but i'm not sure how to do that. Any help would be appreciated.
[
[
As you said in the comment, if the marker length is available, say l0, you can define the length of the desired square as l = l0 * 1.05 or something.
for (int i = 0; i < ids.size(); i++) {
if (ids[i] == 69) {
aruco::drawDetectedMarkers(imageCopy, corners, ids);
// Estimate the pose of the marker
std::vector<cv::Vec3d> rvecs, tvecs;
cv::aruco::estimatePoseSingleMarkers(
corners, l0, camera_matrix, dist_coeffs,
rvecs, tvecs
);
drawSquare(
image_copy, camera_matrix, dist_coeffs, rvecs[i], tvecs[i],
l0
);
}
}
void drawSquare(
cv::InputOutputArray image, cv::InputArray cameraMatrix,
cv::InputArray distCoeffs, cv::InputArray rvec, cv::InputArray tvec,
float l0
)
{
float l = l0 * 1.05; // new square is 5% larger than the aruco marker
float half_l = l / 2.0;
// Define the square on the camera frame (this is 3D since the camera
// frame is 3D).
std::vector<cv::Point3f> squarePoints;
squarePoints.push_back(cv::Point3f(half_l, half_l, 0));
squarePoints.push_back(cv::Point3f(half_l, -half_l, 0));
squarePoints.push_back(cv::Point3f(-half_l, -half_l, 0));
squarePoints.push_back(cv::Point3f(-half_l, half_l, 0));
// Project the square to the image.
std::vector<cv::Point2f> imagePoints;
projectPoints(
squarePoints, rvec, tvec, cameraMatrix, distCoeffs, imagePoints
);
// Draw the square on the image.
cv::line(image, imagePoints[0], imagePoints[1], cv::Scalar(255, 0, 0), 3);
cv::line(image, imagePoints[1], imagePoints[2], cv::Scalar(255, 0, 0), 3);
cv::line(image, imagePoints[2], imagePoints[3], cv::Scalar(255, 0, 0), 3);
cv::line(image, imagePoints[3], imagePoints[0], cv::Scalar(255, 0, 0), 3);
}
I did not test this, but I used a similar code for a different project. If you run into any issues, please let me know. I will update the above code.
How to make my video not delay, in the beginning of the code it's not delay, but if I use the GaussianBlur, morphology operation, and SimpleBlobDetector, the video gets delayed, please someone help me..
Thanks in advance
using namespace cv;
using namespace std;
int _tmain(int argc, _TCHAR* argv[]){
VideoCapture cap(0);
cap.open("file.mp4"); //read the video
if (!cap.isOpened())
{
cout << "Cannot open the video cam" << endl;
return -1;
}
double Width = cap.get(CV_CAP_PROP_FRAME_WIDTH);
double Height = cap.get(CV_CAP_PROP_FRAME_HEIGHT);
cvNamedWindow("MyVideo", CV_WINDOW_AUTOSIZE);
while (1)
{
Mat frame;
bool bSuccess = cap.read(frame);
SimpleBlobDetector::Params params;
// Change thresholds
params.minThreshold = 0;
params.maxThreshold = 255;
params.filterByColor = true;
params.blobColor = 255;
// Filter by Area.
params.filterByArea = true;
params.minArea = 5 ;
// Filter by Circularity
params.filterByCircularity = true;
params.minCircularity = 0.1;
// Filter by Convexity
params.filterByConvexity = true;
params.minConvexity = 0.87;
// Filter by Inertia
params.filterByInertia = true;
params.minInertiaRatio = 0.01;
//crop the image with the pixel i want
Mat blur, crop;
GaussianBlur(frame, blur, Size(15, 15), 0); //blur the image
Point corners[1][4];
corners[0][0] = Point(550, 30); //top left
corners[0][1] = Point(250, 700); //bottom left
corners[0][2] = Point(1100, 700); //bottom right
corners[0][3] = Point(600, 30); //top right
const Point* corner_list[1] = { corners[0] };
int num_points = 4;
int num_polygons = 1;
int line_type = 8;
Mat mask(720, 1280, CV_8UC3, cv::Scalar(0, 0, 0));
fillPoly(mask, corner_list, &num_points, num_polygons, cv::Scalar(255, 255, 255), line_type);
bitwise_and(blur, mask, crop);//combine the image
Mat gray, changeToBlack;
cvtColor(crop, gray, COLOR_BGR2GRAY); //grayscale citra
inRange(gray, Scalar(0), Scalar(0), changeToBlack);
Mat black_image(gray.size(), CV_8U, Scalar(255));
black_image.copyTo(gray, changeToBlack);
Mat thres, tes;
threshold(gray, tes, 51, 255, THRESH_BINARY_INV); //threshold citra and 51 set value
Mat erosi, dilasi, open, close, tophat;
Mat kernel = Mat(3, 3, CV_8UC1, Scalar(1));
morphologyEx(tes, erosi, MORPH_ERODE, kernel, Point(-1, -1), 3);
morphologyEx(erosi, dilasi, MORPH_DILATE, kernel, Point(-1, -1), 20);
vector<KeyPoint> keypoints;
Ptr<SimpleBlobDetector> detector = SimpleBlobDetector::create(params);
detector->detect(dilasi, keypoints);
Mat im_with_keypoints;
drawKeypoints(dilasi, keypoints, im_with_keypoints, Scalar(205, 0, 0), DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
imshow("gray", frame);
imshow("MyVideo", im_with_keypoints);
if (waitKey(30) == 27)
{
cout << "esc key is pressed by user" << endl;
break;
}
}
return 0;
}
Anyone please help me
Oh! All actions and memory allocation inside loop. Try this:
int _tmain(int argc, _TCHAR* argv[]){
VideoCapture cap(0);
cap.open("file.mp4"); //read the video
if (!cap.isOpened())
{
cout << "Cannot open the video cam" << endl;
return -1;
}
double Width = cap.get(CV_CAP_PROP_FRAME_WIDTH);
double Height = cap.get(CV_CAP_PROP_FRAME_HEIGHT);
cvNamedWindow("MyVideo", CV_WINDOW_AUTOSIZE);
Mat frame;
Mat blur, crop;
Mat mask(720, 1280, CV_8UC3, cv::Scalar(0, 0, 0));
Mat gray, changeToBlack;
Mat black_image(gray.size(), CV_8U, Scalar(255));
Mat thres, tes;
Mat erosi, dilasi, open, close, tophat;
Mat kernel = Mat(3, 3, CV_8UC1, Scalar(1));
Mat im_with_keypoints;
SimpleBlobDetector::Params params;
// Change thresholds
params.minThreshold = 0;
params.maxThreshold = 255;
params.filterByColor = true;
params.blobColor = 255;
// Filter by Area.
params.filterByArea = true;
params.minArea = 5 ;
// Filter by Circularity
params.filterByCircularity = true;
params.minCircularity = 0.1;
// Filter by Convexity
params.filterByConvexity = true;
params.minConvexity = 0.87;
// Filter by Inertia
params.filterByInertia = true;
params.minInertiaRatio = 0.01;
vector<KeyPoint> keypoints;
Ptr<SimpleBlobDetector> detector = SimpleBlobDetector::create(params);
while (cap.read(frame))
{
//crop the image with the pixel i want
GaussianBlur(frame, blur, Size(15, 15), 0); //blur the image
Point corners[1][4];
corners[0][0] = Point(550, 30); //top left
corners[0][1] = Point(250, 700); //bottom left
corners[0][2] = Point(1100, 700); //bottom right
corners[0][3] = Point(600, 30); //top right
const Point* corner_list[1] = { corners[0] };
int num_points = 4;
int num_polygons = 1;
int line_type = 8;
fillPoly(mask, corner_list, &num_points, num_polygons, cv::Scalar(255, 255, 255), line_type);
bitwise_and(blur, mask, crop);//combine the image
cvtColor(crop, gray, COLOR_BGR2GRAY); //grayscale citra
inRange(gray, Scalar(0), Scalar(0), changeToBlack);
black_image.copyTo(gray, changeToBlack);
threshold(gray, tes, 51, 255, THRESH_BINARY_INV); //threshold citra and 51 set value
morphologyEx(tes, erosi, MORPH_ERODE, kernel, Point(-1, -1), 3);
morphologyEx(erosi, dilasi, MORPH_DILATE, kernel, Point(-1, -1), 20);
detector->detect(dilasi, keypoints);
drawKeypoints(dilasi, keypoints, im_with_keypoints, Scalar(205, 0, 0), DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
imshow("gray", frame);
imshow("MyVideo", im_with_keypoints);
if (waitKey(1) == 27)
{
cout << "esc key is pressed by user" << endl;
break;
}
}
return 0;
}
I'm newbie OpenCV. I am using opencv for find position attach a stamp in image. The stamp can't overlap with other object in image.
Example binary image with white region is object on image, black region is none object
Example image
Result : Find rect in black region (in white circle) can attach stamp
Result imagge
Please help me find rect in black region same blue rect.
Thank you!
If you know about rectangles count then it can use kmeans for clusterization points.
First get only blue points and binarization they:
cv::Mat img = cv::imread("NQdmi.png", cv::IMREAD_COLOR);
std::vector<cv::Mat> chans;
cv::split(img, chans);
cv::Mat diff;
cv::absdiff(chans[2], chans[1], diff);
cv::threshold(diff, diff, 1, 255, cv::THRESH_BINARY);
cv::imshow("diff", diff);
Only blue points:
Clusterization points and find rotated rectangles:
std::vector<cv::Point2f> points;
for (int y = 0; y < diff.rows; ++y)
{
for (int x = 0; x < diff.cols; ++x)
{
if (diff.at<uchar>(y, x))
{
points.emplace_back(x, y);
}
}
}
cv::Mat pointsKmeans(points.size(), 1, CV_32FC2, &points[0]);
cv::Mat labels;
int clusterCount = 2;
cv::Mat centers;
cv::kmeans(pointsKmeans, clusterCount, labels,
cv::TermCriteria(cv::TermCriteria::EPS+cv::TermCriteria::COUNT, 100, 1.0),
3, cv::KMEANS_PP_CENTERS, centers);
std::vector<cv::Point2f> points1;
std::vector<cv::Point2f> points2;
cv::Mat draw = img.clone();
for (size_t i = 0; i < points.size(); ++i)
{
int clusterIdx = labels.at<int>(i);
if (clusterIdx > 0)
{
cv::circle(draw, points[i], 2, cv::Scalar(255, 0, 0), cv::FILLED, cv::LINE_AA);
points1.push_back(points[i]);
}
else
{
cv::circle(draw, points[i], 2, cv::Scalar(0, 0, 255), cv::FILLED, cv::LINE_AA);
points2.push_back(points[i]);
}
}
auto DrawRRect = [draw](const std::vector<cv::Point2f>& pp)
{
cv::RotatedRect rr = cv::minAreaRect(pp);
cv::Point2f corners[4];
rr.points(corners);
cv::line(draw, corners[0], corners[1], cv::Scalar(0, 255, 0), 2);
cv::line(draw, corners[1], corners[2], cv::Scalar(0, 255, 0), 2);
cv::line(draw, corners[2], corners[3], cv::Scalar(0, 255, 0), 2);
cv::line(draw, corners[3], corners[0], cv::Scalar(0, 255, 0), 2);
};
DrawRRect(points1);
DrawRRect(points2);
cv::imshow("draw", draw);
Result:
I have followed this article on how to calculate and deskew an image for better Tesseract OCR results: http://felix.abecassis.me/2011/10/opencv-rotation-deskewing/
The correct angle is calculated, but the text is never actually rotated.
These are the methods I am using:
+(UIImage *) prepareImage: (UIImage *)image{
return deskew(image, computeSkew(image));
}
// Organization -> Deskewing
double computeSkew(UIImage *image)
{
Mat src;
UIImageToMat(image, src);
cv::Size size = src.size();
bitwise_not(src, src);
vector<Vec4i> lines;
HoughLinesP(src, lines, 1, CV_PI/180, 100, size.width / 2.f, 20);
Mat disp_lines(size, CV_8UC1, Scalar(0, 0, 0));
double angle = 0.;
unsigned nb_lines = lines.size();
for (unsigned i = 0; i < nb_lines; ++i)
{
line(disp_lines, cv::Point(lines[i][0], lines[i][1]),
cv::Point(lines[i][2], lines[i][3]), Scalar(255, 0 ,0));
angle += atan2((double)lines[i][3] - lines[i][1],
(double)lines[i][2] - lines[i][0]);
}
angle /= nb_lines; // mean angle, in radians.
cout << angle << endl;
return angle;
}
UIImage* deskew(UIImage *image, double angle)
{
Mat img;
UIImageToMat(image, img);
bitwise_not(img, img);
vector<cv::Point> points;
Mat_<uchar>::iterator it = img.begin<uchar>();
Mat_<uchar>::iterator end = img.end<uchar>();
for (; it != end; ++it)
if (*it)
points.push_back(it.pos());
RotatedRect box = minAreaRect(Mat(points));
Mat rot_mat = getRotationMatrix2D(box.center, angle, 1);
Mat rotated;
warpAffine(img, rotated, rot_mat, img.size(), INTER_CUBIC);
return MatToUIImage(rotated);
}
UIImageToMat and MatToUIImage are reliable methods that convert back and forth. I have also tried to return the angle in both radians and degrees. Both times the image returned from the prepareImage function is still tilted at the same angle as the original image.