问题描述
- 要做一个C++项目 关于自动抠像的
-
VS2010 在新建项目的时候 我该用控制台应用程序呢 还是win32程序创建项目呢? 求解释 我们在学C++的时候一直在用控制台应用程序 可是 要做项目 不应该是有界面 可视度比较强的项目吗 但是 并没有学过win32编程诶。。 这个不需要另外学吗。。
解决方案
这要看你的算法主要不主要了,现在处理方面有一些库,实际上你只需要是控制台应用就行,一些界面可以调用库里
解决方案二:
可以调用库函数来实现
解决方案三:
控制台应用程序
#include "cv.h"
#include "highgui.h"
#include
#include
#pragma comment(lib, "opencv_core2410d.lib")
#pragma comment(lib, "opencv_highgui2410d.lib")
#pragma comment(lib, "opencv_imgproc2410d.lib")
#pragma comment(lib, "opencv_objdetect2410d.lib")
#pragma comment(lib, "opencv_video2410d.lib")
#pragma comment(lib, "libjasperd.lib")
#pragma comment(lib, "IlmImfd.lib")
#pragma comment(lib, "libjpegd.lib")
#pragma comment(lib, "libpngd.lib")
#pragma comment(lib, "libtiffd.lib")
#pragma comment(lib, "zlibd.lib")
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "gdi32.lib")
#pragma comment(lib, "advapi32.lib")
#pragma comment(lib, "ole32.lib")
#pragma comment(lib, "oleaut32.lib")
#pragma comment( lib, "vfw32.lib" )
#pragma comment( lib, "comctl32.lib" )
static CvMemStorage*storage = 0;
static CvHaarClassifierCascade*cascade = 0;
void detect_and_draw(IplImage* image);
const char*cascade_name = "haarcascade_frontalface_alt.xml";//人脸检测分类器
IplImage image_c = 0, *hsv = 0, *hue = 0, *mask = 0, *backproject = 0, *histimg = 0;
//用HSV中的Hue分量进行跟踪
CvHistogram *hist = 0;//直方图类
int select_object = 0;
int track_object = 0;
CvPoint origin;
CvRect selection;
CvRect track_window;
CvBox2D track_box;
CvConnectedComp track_comp;
int hdims = 16;//划分直方图bins的个数,越多越精确
float hranges_arr[] = { 0, 180 };//像素值的范围
float hranges = hranges_arr;//用于初始化CvHistogram类
int vmin = 10, vmax = 256, smin = 30;//用于范围
void on_mouse(int event, int x, int y, int flags, void* param);
CvScalar hsv2rgb(float hue);
int on_off = 0;
int main(int argc, char**argv)
{
CvCapture* capture = 0;
IplImage frame, *frame_copy = 0;
const char*input_name;
char c;
input_name = argc> 1 ? argv[1] : 0;
cascade = (CvHaarClassifierCascade)cvLoad(cascade_name, 0, 0, 0);
if (!cascade)//如果没有找到分类器,输出以下
{
fprintf(stderr,"ERROR: Could notload classifier cascaden");
return -1;
}
storage = cvCreateMemStorage(0);
capture = cvCaptureFromCAM(!input_name ? 0 : input_name[0] - '0');//读取摄像头
if(!capture)//如果没有摄像头读取视频文件
capture = cvCaptureFromAVI("检测.avi");
cvNamedWindow("result", 1);//创建窗口
cvSetMouseCallback("result", on_mouse, 0);//设置鼠标回调函数
if (capture)
{
for (;;)
{
frame = cvQueryFrame(capture);
if (!frame)
break;
if( !frame_copy)
frame_copy= cvCreateImage( cvSize(frame->width,frame->height), IPL_DEPTH_8U,frame->nChannels );
if (on_off)
{
if (frame->origin == IPL_ORIGIN_TL)
cvCopy(frame, frame_copy, 0);
else cvFlip(frame, frame_copy, 0);
detect_and_draw(frame_copy);
}
else
{
if (!image_c)//image为0,表明刚开始还未对image操作过,先建立一些缓冲区
{
image_c = cvCreateImage(cvGetSize(frame), 8, 3);
image_c->origin = frame->origin;
hsv = cvCreateImage(cvGetSize(frame), 8, 3);
hue = cvCreateImage(cvGetSize(frame), 8, 1);
mask = cvCreateImage(cvGetSize(frame), 8, 1);
//分配掩膜图像空间
backproject = cvCreateImage(cvGetSize(frame), 8, 1);
//分配反向投影图空间,大小一样,单通道
hist = cvCreateHist(1, &hdims, CV_HIST_ARRAY, &hranges, 1);
//分配直方图空间
}
cvCopy(frame, image_c, 0);
cvCvtColor(image_c, hsv, CV_BGR2HSV);//把图像从RGB表色系转为HSV表色系
if (track_object)//track_object非零,表示有需要跟踪的物体
{
cvInRangeS(hsv, cvScalar(0, smin, MIN(vmin, vmax), 0),
cvScalar(180, 256, MAX(vmin, vmax), 0), mask);
//制作掩膜板,只处理像素值为H:0~180,S:smin~256,V:vmin~vmax之间的部分
cvSplit(hsv, hue, 0, 0, 0);//分离H分量
if (track_object < 0)
//如果需要跟踪的物体还没有进行属性提取,则进行选取框类的图像属性提取
{
float max_val = 0.f;
cvSetImageROI(hue, selection);//设置原选择框为ROI
cvSetImageROI(mask, selection);//设置掩膜板选择框为ROI
cvCalcHist(&hue, hist, 0, mask);//得到选择框内且满足掩膜板内的直方图
cvGetMinMaxHistValue(hist, 0, &max_val, 0, 0);
cvConvertScale(hist->bins, hist->bins, max_val ? 255. / max_val : 0., 0);
// 对直方图的数值转为0~255
cvResetImageROI(hue);//去除ROI
cvResetImageROI(mask);//去除ROI
track_window = selection;
track_object = 1;//置track_object为1,表明属性提取完成
}
cvCalcBackProject(&hue, backproject, hist);//计算hue的反向投影图
cvAnd(backproject, mask, backproject, 0);//得到掩膜内的反向投影
cvCamShift(backproject, track_window,
cvTermCriteria(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 10, 1),
&track_comp, &track_box);//使用MeanShift算法对backproject中的内容进行搜索,返回跟踪结果
track_window = track_comp.rect;//得到跟踪结果的矩形框
if (image_c->origin)
track_box.angle = -track_box.angle;
cvEllipseBox(image_c, track_box, CV_RGB(255, 0, 0), 3, CV_AA, 0);
//画出跟踪结果的位置
}
if (select_object && selection.width > 0 && selection.height > 0)//如果正处于物体选择,画出选择框
{
cvSetImageROI(image_c, selection);
cvXorS(image_c, cvScalarAll(255), image_c, 0);
cvResetImageROI(image_c);
}
cvShowImage("result", image_c);
}
c = cvWaitKey(10);
if ((char)c == 27)
break;
else if ((char)c == 'b')
on_off = 1 - on_off;
}
cvReleaseImage(&frame_copy);
cvReleaseCapture(&capture);
}
cvDestroyWindow("result");
return 0;
}
void on_mouse(int event, int x, int y, int flags, void* param)
//鼠标回调函数,该函数用鼠标进行跟踪目标的选择
{
if (!image_c)
return;
if (image_c->origin)
y = image_c->height - y;//如果图像原点坐标在左下,则将其改为左上
if (select_object)//select_object为1,表示在用鼠标进行目标选择
//此时对矩形类selection用当前的鼠标位置进行设置
{
selection.x = MIN(x, origin.x);
selection.y = MIN(y, origin.y);
selection.width = selection.x + CV_IABS(x - origin.x);
selection.height = selection.y + CV_IABS(y - origin.y);
selection.x = MAX(selection.x, 0);
selection.y = MAX(selection.y, 0);
selection.width = MIN(selection.width, image_c->width);
selection.height = MIN(selection.height, image_c->height);
selection.width -= selection.x;
selection.height -= selection.y;
}
switch (event)
{
case CV_EVENT_LBUTTONDOWN:
//鼠标按下,开始点击选择跟踪物体
origin = cvPoint(x, y);
selection = cvRect(x, y, 0, 0);
select_object = 1;
break;
case CV_EVENT_LBUTTONUP:
//鼠标松开,完成选择跟踪物体
select_object = 0;
if (selection.width > 0 && selection.height > 0)
//如果选择物体有效,则打开跟踪功能
track_object = -1;
break;
}
}
CvScalar hsv2rgb(float hue)//用于将Hue量转换成RGB量
{
int rgb[3], p, sector;
static const int sector_data[][3] =
{ { 0, 2, 1 }, { 1, 2, 0 }, { 1, 0, 2 }, { 2, 0, 1 }, { 2, 1, 0 }, { 0, 1, 2 } };
hue *= 0.033333333333333333333333333333333f;
sector = cvFloor(hue);
p = cvRound(255 * (hue - sector));
p ^= sector & 1 ? 255 : 0;
rgb[sector_data[sector][0]] = 255;
rgb[sector_data[sector][1]] = 0;
rgb[sector_data[sector][2]] = p;
return cvScalar(rgb[2], rgb[1], rgb[0], 0);
}
void detect_and_draw(IplImage* img)
{
static CvScalar colors[] =
{
{ { 0, 0, 255 } },
{ { 0, 128, 255 } },
{ { 0, 255, 255 } },
{ { 0, 255, 0 } },
{ { 255, 128, 0 } },
{ { 255, 255, 0 } },
{ { 255, 0, 0 } },
{ { 255, 0, 255 } }
};
double scale = 1.3;
IplImage* gray = cvCreateImage(cvSize(img->width, img->height), 8, 1);
IplImage* small_img = cvCreateImage(cvSize(cvRound(img->width / scale), cvRound(img->height / scale)), 8, 1);
int i;
cvCvtColor(img, gray, CV_BGR2GRAY);
cvResize(gray, small_img, CV_INTER_LINEAR);
cvEqualizeHist(small_img, small_img);
cvClearMemStorage(storage);
if (cascade)
{
double t = (double)cvGetTickCount();
CvSeq* faces = cvHaarDetectObjects(small_img, cascade, storage, 1.1, 2, 0/*CV_HAAR_DO_CANNY_PRUNING*/, cvSize(30, 30));//检测人脸返回矩形人脸
t = (double)cvGetTickCount() - t;
printf("detection time = %gmsn", t / ((double)cvGetTickFrequency()*1000.));
for (i = 0; i < (faces ? faces->total : 0); i++)//找到矩形中心,把矩形转化为圆形
{
CvRect*r = (CvRect*)cvGetSeqElem(faces, i);
CvPoint center;
int radius;
center.x = cvRound((r->x + r->width*0.5)*scale);
center.y = cvRound((r->y + r->height*0.5)*scale);
radius = cvRound((r->width + r->height)*0.25*scale);
cvCircle(img, center, radius, colors[i % 8], 3, 8, 0);
}
}
cvShowImage("result", img);
cvReleaseImage(&gray);
cvReleaseImage(&small_img);
}
解决方案四:
控制台程序还是win32程序,是你的程序的交互方式。无论哪种交互方式,肯定都能实现抠像的算法。
交互方式和抠像本身没有必然的联系。到底选哪种,当然看你的设计需要。
不过推荐使用OpenCV做控制台程序。这样可以专心实现抠像算法本身,而不必再去学习可视化程序设计。
解决方案五:
可以调用库函数来实现