OpenCV 从摄像头裁剪实时提要
Posted
技术标签:
【中文标题】OpenCV 从摄像头裁剪实时提要【英文标题】:OpenCV crop live feed from camera 【发布时间】:2013-06-27 20:18:21 【问题描述】:如何在 OpenCV (640x320) 中从相机正确获取一个分辨率馈送,但将其切成两半并仅显示帧的一半 (320x240)。所以不是缩小,而是实际裁剪。我正在使用 OpenCV 2.4.5、VS2010 和 C++
这个非常标准的代码获得了 640x480 的输入分辨率,我对裁剪分辨率进行了一些更改为 320x240。 我应该使用 Mat 而不是 IplImage,如果可以,最好的方法是什么?
#include "stdafx.h"
#include <iostream>
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
using namespace std;
char key;
int main()
cvNamedWindow("Camera_Output", 1); //Create window
CvCapture* capture = cvCaptureFromCAM(1); //Capture using camera 1 connected to system
cvSetCaptureProperty( capture, CV_CAP_PROP_FRAME_WIDTH, 640 );
cvSetCaptureProperty( capture, CV_CAP_PROP_FRAME_HEIGHT, 480 );
while(1) //Create loop for live streaming
IplImage* framein = cvQueryFrame(capture); //Create image frames from capture
/* sets the Region of Interest - rectangle area has to be __INSIDE__ the image */
cvSetImageROI(framein, cvRect(0, 0, 320, 240));
/* create destination image - cvGetSize will return the width and the height of ROI */
IplImage *frameout = cvCreateImage(cvGetSize(framein), framein->depth, framein->nChannels);
/* copy subimage */
cvCopy(framein, frameout, NULL);
/* always reset the Region of Interest */
cvResetImageROI(framein);
cvShowImage("Camera_Output", frameout); //Show image frames on created window
key = cvWaitKey(10); //Capture Keyboard stroke
if (char(key) == 27)
break; //ESC key loop will break.
cvReleaseCapture(&capture); //Release capture.
cvDestroyWindow("Camera_Output"); //Destroy Window
return 0;
【问题讨论】:
是的,如果你用 c++ 标记它,你应该使用 cv::Mat 【参考方案1】:我认为您不会检查您是否收到CvCapture
。在我只有一个摄像头的系统上,您的代码不起作用,因为您查询摄像头 1。但第一个摄像头应该是 0 因此更改此代码。
CvCapture* capture = cvCaptureFromCAM(1); //Capture using camera 1 connected to system
到(注意我把1
改成0
):
CvCapture* capture = cvCaptureFromCAM(0); //Capture using camera 1 connected to system
if (! capture )
/*your error handling*/
除此之外,您的代码似乎对我有用。您还可以检查其他指针值是否为 NULL。
【讨论】:
实际上我的系统上有 2 个摄像头,这段代码用于从摄像头 1 获取信息,这就是为什么它是 cvCaptureFromCAM(1);至于错误检查,我同意,我应该添加错误处理程序。 @NenadBulatovic 也许您可以重新表述您的问题并详细说明您遇到的错误,因为正如我所说,您的代码似乎可以在我的系统上使用摄像头 0。我也认为您的问题可能会碰到顶部。【参考方案2】:您可以通过调用以下函数轻松裁剪视频。
cvSetMouseCallback("image", mouseHandler, NULL);
mouseHandler
函数就是这样的。
void mouseHandler(int event, int x, int y, int flags, void* param)
if (event == CV_EVENT_LBUTTONDOWN && !drag)
/* left button clicked. ROI selection begins */
select_flag=0;
point1 = Point(x, y);
drag = 1;
if (event == CV_EVENT_MOUSEMOVE && drag)
/* mouse dragged. ROI being selected */
Mat img1 = img.clone();
point2 = Point(x, y);
rectangle(img1, point1, point2, CV_RGB(255, 0, 0), 3, 8, 0);
imshow("image", img1);
if (event == CV_EVENT_LBUTTONUP && drag)
point2 = Point(x, y);
rect = Rect(point1.x,point1.y,x-point1.x,y-point1.y);
drag = 0;
roiImg = img(rect);
if (event == CV_EVENT_LBUTTONUP)
/* ROI selected */
select_flag = 1;
drag = 0;
详情可以访问以下链接:How to Crop Video from Webcam using OpenCV
【讨论】:
链接已失效【参考方案3】:这在 python 中很容易......但关键思想是 cv2 数组可以被引用和切片。你只需要一片framein
。
以下代码从 (0,0) 到 (320,240) 取一个切片。请注意,numpy 数组按列优先级进行索引。
# Required modules
import cv2
# Constants for the crop size
xMin = 0
yMin = 0
xMax = 320
yMax = 240
# Open cam, decode image, show in window
cap = cv2.VideoCapture(0) # use 1 or 2 or ... for other camera
cv2.namedWindow("Original")
cv2.namedWindow("Cropped")
key = -1
while(key < 0):
success, img = cap.read()
cropImg = img[yMin:yMax,xMin:xMax] # this is all there is to cropping
cv2.imshow("Original", img)
cv2.imshow("Cropped", cropImg)
key = cv2.waitKey(1)
cv2.destroyAllWindows()
【讨论】:
@NenadBulatovic 在 python 中,cv2 数组是 numpy 数组,因此可以对它们进行通常的基于数组索引的操作。 cv::Mat 构造函数还应该生成一个数组,让您可以通过索引获取切片。【参考方案4】:从实时相机中裁剪人脸的工作示例
void CropFaces::DetectAndCropFaces(Mat frame, string locationToSaveFaces)
std::vector<Rect> faces;
Mat frame_gray;
// Convert to gray scale
cvtColor(frame, frame_gray, COLOR_BGR2GRAY);
// Equalize histogram
equalizeHist(frame_gray, frame_gray);
// Detect faces
face_cascade.detectMultiScale(frame_gray, faces, 1.1, 3,
0 | CASCADE_SCALE_IMAGE, Size(30, 30));
// Iterate over all of the faces
for (size_t i = 0; i < faces.size(); i++)
// Find center of faces
Point center(faces[i].x + faces[i].width / 2, faces[i].y + faces[i].height / 2);
Mat face = frame_gray(faces[i]);
std::vector<Rect> eyes;
Mat croppedRef(frame, faces[i]);
cv::Mat cropped;
// Copy the data into new matrix
croppedRef.copyTo(cropped);
string fileName = locationToSaveFaces+ "\\face_" + to_string(faces[i].x) + ".jpg";
resize(cropped, cropped, Size(65, 65));
imwrite(fileName, cropped);
// Display frame
imshow("DetectAndSave", frame);
void CropFaces::PlayVideoForCropFaces(string locationToSaveFaces)
VideoCapture cap(0); // Open default camera
Mat frame;
face_cascade.load("haarcascade_frontalface_alt.xml"); // load faces
while (cap.read(frame))
DetectAndCropFaces(frame, locationToSaveFaces); // Call function to detect faces
if (waitKey(30) >= 0) // pause
break;
【讨论】:
但是是否也可以将检测到的面部的实时流作为视频返回?不仅将人脸保存为图片,而且将感兴趣区域框(人脸)显示为新视频?以上是关于OpenCV 从摄像头裁剪实时提要的主要内容,如果未能解决你的问题,请参考以下文章
OpenCV 网络摄像头提要未在 PictureBox Visual Studio 2015 中显示
使用OpenCV Android SDK从摄像头帧实时检测人脸
OpenCV 和 python - 裁剪网络摄像头流并将其保存到文件