我发现这段代码我不记得了。
问题是,它显示了图片和检测到的面部,只有在detectAndDisplay()
的第二次调用之后,并且作者故意使其成为无限循环,但我无法理解为什么。
有什么想法吗?
感谢您提前提供任何帮助。
代码:
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
using namespace std;
using namespace cv;
// Function Headers
void detectAndDisplay(Mat frame);
// Global variables
// Copy this file from opencv/data/haarscascades to target folder
string face_cascade_name = "c:/haarcascade_frontalface_alt.xml";
CascadeClassifier face_cascade;
string window_name = "Capture - Face detection";
int filenumber; // Number of file to be saved
string filename;
// Function main
int main(void)
{
// Load the cascade
if (!face_cascade.load(face_cascade_name))
{
printf("--(!)Error loading\n");
int ch = std::cin.get();
return (-1);
};
// Read the image file
Mat frame = imread("C:/lena.jpg");
for (;;) // -----> here. why an infinite loop? and why it works at the second turn of this loop ?
{
// Apply the classifier to the frame
if (!frame.empty())
{
detectAndDisplay(frame);
}
else
{
printf(" --(!) No captured frame -- Break!");
int ch = std::cin.get();
break;
}
int c = waitKey(10);
if (27 == char(c))
{
break;
}
}
return 0;
}
// Function detectAndDisplay
void detectAndDisplay(Mat frame)
{
std::vector<Rect> faces;
Mat frame_gray;
Mat crop;
Mat res;
Mat gray;
string text;
stringstream sstm;
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
for (ic = 0; ic < faces.size(); ic++) // Iterate through all current elements (detected faces)
{
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);
resize(crop, res, Size(128, 128), 0, 0, INTER_LINEAR); // This will be needed later while saving images
cvtColor(crop, gray, CV_BGR2GRAY); // Convert cropped image to Grayscale
// Form a filename
filename = "";
stringstream ssfn;
ssfn << filenumber << ".png";
filename = ssfn.str();
filenumber++;
imwrite(filename, gray);
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);
}
// Show image
sstm << "Crop area size: " << roi_b.width << "x" << roi_b.height << " Filename: " << filename;
text = sstm.str();
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");
}
感谢Mhd.Tahawi,我还找到了this code,它再次包含while(true)
循环。我只是看不出原因。
此外,如果我想在续集的图像或视频中检测面部怎么办?然后我被困在第一张图片上了?
答案 0 :(得分:1)
等待用户输入不全部。
即使您不关心键盘输入,也必须调用waitKey
。
来自OpenCV DOC:
此函数是HighGUI中唯一可以获取和处理的方法 事件,因此需要定期调用正常事件 处理除非在需要的环境中使用HighGUI 照顾事件处理
在你的代码上:
imshow("original", frame);
imshow()
是HighGui的函数,代码需要调用waitKey
,以便处理其事件循环。如果您不调用waitKey,则HighGui无法处理重绘等窗口事件。
所以,基本上,你允许调用waitKey
的HighGui进程窗口事件。
答案 1 :(得分:0)
这只是因为作者希望程序继续运行,直到他从用户收到一个键来结束它,就是这样。
该计划旨在处理实时视频流,即全部。 它与实际处理没有任何关系。
您可以将代码从循环中取出并使用它处理单个图像,它仍然可以以相同的方式运行
修改强> 我有相同的情况,但我正在使用网络摄像头,而不是从文件中读取。硬件启动太慢,捕获一个帧然后将其发送到我的程序来处理它。 这是我在我的案例中的代码:
VideoCapture capture;
Mat frame;
capture.open( 0 );
if( capture.isOpened() )
{
for(;;)
{
capture >> frame;
if( !frame.empty() )
{
detectAndDisplay( frame );
}
int c = waitKey(5);
if( (char)c == 'c' ) { break; }
}