#include <stdio.h>
#include <cv.h>
#include <highgui.h>
#include <cvcam.h>
#define refBlue 255
#define refGreen 255
#define refRed 255
#define TH 150 //門檻值
int main()
{
CvCapture *capture;
IplImage *frame;
IplImage *img;
IplImage *grey;
IplImage *logoImg;
IplImage *logoImg2;
float SkinPixelNumber;
float SkinPixelX;
float SkinPixelY;
int MouseX=0,MouseY=0;
logoImg=cvLoadImage("images.jpg");
logoImg2=cvLoadImage("images2.jpg");
capture=cvCreateCameraCapture( 0 );
frame = cvQueryFrame(capture);
grey = cvCreateImage(cvSize(frame->width,frame->height), IPL_DEPTH_8U, 1);
img = cvCreateImage(cvSize(frame->width,frame->height), IPL_DEPTH_8U, 3);
while(1)
{
frame = cvQueryFrame(capture);
cvCvtColor(frame, frame, CV_BGR2YCrCb);
cvInRangeS(frame, cvScalar(0,137,77), cvScalar(256,177,127),grey); //判斷膚色轉換成黑白影像
frame = cvQueryFrame(capture); //在抓一次原本的視訊影像
cvLine(frame,cvPoint(frame->width/2,0),cvPoint(frame->width/2,frame->height),CV_RGB(255,0,0),5,8,0);
//畫線 X軸的一半位置 和Y軸0的位置 到 X軸的一半位置 和Y軸的全高
for (int y=0; y<logoImg->height; y++) { //讀取
uchar* ptr1=(uchar*) (logoImg->imageData +y*logoImg->widthStep);
uchar* ptr2=(uchar*) (frame->imageData +(y)*frame->widthStep);
for (int x=0; x<logoImg->width; x++) {
int D= (ptr1[3*x] - refBlue) * (ptr1[3*x] - refBlue) + // 計算白色色彩值範圍
(ptr1[3*x+1] - refGreen) * (ptr1[3*x+1] -refGreen) +
(ptr1[3*x+2] - refRed) * (ptr1[3*x+2] - refRed);
if(sqrt(D) > TH){ //開根號讓數值大於門檻值的部分顯示 去除背景
ptr2[3*(x+50)]=ptr1[3*(x)] ;
ptr2[3*(x+50)+1]=ptr1[3*(x)+1] ;
ptr2[3*(x+50)+2]=ptr1[3*(x)+2] ;
}
}
}
for (int y=0; y<logoImg2->height; y++) {
uchar* ptr1=(uchar*) (logoImg2->imageData +y*logoImg2->widthStep);
uchar* ptr2=(uchar*) (frame->imageData +(y)*frame->widthStep);
for (int x=0; x<logoImg2->width; x++) {
int D= (ptr1[3*x] - refBlue) * (ptr1[3*x] - refBlue) +
(ptr1[3*x+1] - refGreen) * (ptr1[3*x+1] -refGreen) +
(ptr1[3*x+2] - refRed) * (ptr1[3*x+2] - refRed);
if(sqrt(D) > TH){
ptr2[3*(x+215)]=ptr1[3*(x)] ;
ptr2[3*(x+215)+1]=ptr1[3*(x)+1] ;
ptr2[3*(x+215)+2]=ptr1[3*(x)+2] ;
}
}
}
for (int y=0; y<grey->height; y++) {
uchar* ptr1=(uchar*) (frame->imageData +y*frame->widthStep);
uchar* ptr2=(uchar*) (grey->imageData +y*grey->widthStep);
for (int x=0; x<grey->width; x++) {
if(ptr2[x]==255) {
SkinPixelNumber++;
SkinPixelX+=x;
SkinPixelY+=y;
}
//計算所有膚色值將x,y值總數相加
}
}
if (SkinPixelNumber>0) { //抓膚色的中心點
MouseX=(int)(SkinPixelX/SkinPixelNumber);
MouseY=(int)(SkinPixelY/SkinPixelNumber)-120.0;
}
for (int y=0; y<logoImg->height; y++) {
uchar* ptr1=(uchar*) (logoImg->imageData +y*logoImg->widthStep);
uchar* ptr2=(uchar*) (frame->imageData +(y+MouseY)*frame->widthStep);
for (int x=0; x<logoImg->width; x++) {
int D= (ptr1[3*x] - refBlue) * (ptr1[3*x] - refBlue) +
(ptr1[3*x+1] - refGreen) * (ptr1[3*x+1] -refGreen) +
(ptr1[3*x+2] - refRed) * (ptr1[3*x+2] - refRed);
if(MouseX < 150)if(sqrt(D) > TH){ //判斷虛擬滑鼠小於視窗大小150時顯示左邊的圖片
ptr2[3*(x+MouseX-50)]=ptr1[3*(x)] ;
ptr2[3*(x+MouseX-50)+1]=ptr1[3*(x)+1] ;
ptr2[3*(x+MouseX-50)+2]=ptr1[3*(x)+2] ;
}
}
}
for (int y=0; y<logoImg2->height; y++) {
uchar* ptr1=(uchar*) (logoImg2->imageData +y*logoImg2->widthStep);
uchar* ptr2=(uchar*) (frame->imageData +(y+MouseY)*frame->widthStep);
for (int x=0; x<logoImg2->width; x++) {
int D= (ptr1[3*x] - refBlue) * (ptr1[3*x] - refBlue) +
(ptr1[3*x+1] - refGreen) * (ptr1[3*x+1] -refGreen) +
(ptr1[3*x+2] - refRed) * (ptr1[3*x+2] - refRed);
if(MouseX > 150)if(sqrt(D) > TH){ //判斷虛擬滑鼠大於視窗大小150時顯示右邊的圖片
ptr2[3*(x+MouseX)]=ptr1[3*(x)] ;
ptr2[3*(x+MouseX)+1]=ptr1[3*(x)+1] ;
ptr2[3*(x+MouseX)+2]=ptr1[3*(x)+2] ;
}
}
}
cvShowImage("Webcam", frame);
cvShowImage("98360242", grey);
SkinPixelNumber=0;
SkinPixelX=0;
SkinPixelY=0;
cvWaitKey(20);
}
cvReleaseCapture(&capture);
cvDestroyWindow("Webcam");
}
試後心得:
臨時抱佛腳的後果就是題目一下來完全不曉得該從何著手,最一開始畫線的部分只曉得要用cvLine卻忘了做長與寬位置的調整,所以線畫出來一直是歪的,不符合題目需求,考試過程最後也只有把圖片放到虛擬滑鼠上,但尚未做判斷,所以無法讓圖片跟著頭移動而變換皇冠。
考試結束,詢問有成功的同學了解題最主要目的,其實加入我們需要的材料後只要靠一些判斷及調整就可以完成。在找中心點時,只要一超出範圍就會不能run,所以在測試很多遍後想到可以在MouseY=(int)(SkinPixelY/SkinPixelNumber)這裡做更改,只要在後面-120.0就可以解決讓圖片改在中心點向上移動的位置的問題。放入圖片及去背後,因為我們是要讓圖片在左右兩邊做更動,所以設定MouseX小於視窗的一半為左邊,大於一半的範圍即為右邊,將這些基本設定都解決完畢後我的戴皇冠終於完成。
沒有留言:
張貼留言