ManyCamShiftAreaDesition.h
-------------------------------------
#pragma once
#include "cvbase.h"
#include "opencv2/video/tracking.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
#include <ctype.h>
#include <stdio.h>
using namespace cv;
using namespace std;
class CamShiftResult
{
public:
int frameNum;
RotatedRect trackBox;
};
class CamShiftArea
{
public:
CamShiftArea(void);
CamShiftArea(int width,int height);
~CamShiftArea(void);
Rect selection;
bool selectObject;
int trackObject;
Mat histimg;
Mat backproj;
Mat hist;
Rect trackWindow;
Mat positionData;
Mat graph;
int beforeAreaNum;
int beforeTime;
FILE *csvFile;
vector<Point2f> points;
vector<CamShiftResult *> results;
int getTimePoint(int x,int y);
int getAreaNum(Point2f p);
void drawGraph(Mat graph,int time,int areaNum);
void drawLines(Mat image,cv::Scalar color,bool colorFlag);
void drawTarget(Mat image,cv::Scalar color,int num);
void drawArea(Mat image);
void calucurateCamShit(Mat image,int num,int nowTime,int _vmin, int _vmax ,int smin,bool backprojMode);
};
class ManyCamShiftAreaDesition:
public CVBase
{
public:
ManyCamShiftAreaDesition(void);
~ManyCamShiftAreaDesition(void);void init(void);
void mainloop(void);
void term(void);
void mouseEvent (int event, int x, int y, int flags, void *param);
void keyEvent(char c);
void drawNowPoint(Mat graph,int num);
void startCreateArea(int x, int y);
void endCreateArea(int x, int y);
void timeShift(int x, int y);
void createWork(int x,int y);
int speed;
bool paused;
int targetArea;
int waitSprrd;
vector<CamShiftArea *> areas;
CamShiftArea *tmpArea;
Mat image;
Mat positionData;
int caluculatedNum;
bool backprojMode;
bool showHist;
Point origin;
Rect selection;
int vmin;
int vmax;
int smin;
VideoCapture cap;
vector<Point2f> tmpPoints;
};
ManyCamShiftAreaDesition.cpp
---------------------------------------
#include "ManyCamShiftAreaDesition.h"
void on_mouse (int event, int x, int y, int flags, void *param = NULL);
Scalar convertNum2Scalar(int num)
{
num++;
printf("%d,%d,%d\n",((int)num%(255*255))%255, (int)((int)num%(255*255))/255, (int)num/255/255);
return Scalar(((int)num%(255*255))%255, (int)((int)num%(255*255))/255, (int)num/255/255);
}
Scalar convertSmallNum2Scalar(int num)
{
int r,g,b;
if(num == 0){
r = 255;
g = 100;
b = 100;
}else if(num == 1){
r = 255;
g = 255;
b = 100;
}else if(num == 2){
r = 255;
g = 100;
b = 255;
}else if(num == 3){
r = 100;
g = 255;
b = 100;
}else if(num == 4){
r = 100;
g = 255;
b = 255;
}else if(num == 5){
r = 100;
g = 100;
b = 255;
}else{
r = 255;
g = 255;
b = 255;
}
return Scalar(r,g,b);
}
Scalar convertMidiumNum2Scalar(int num)
{
int r,g,b;
num %= (255*6);
if(num <255){
r = 255;
g = num;
b = 0;
}else if(num < 255 * 2){
r = 255-(num - 255 * 1);
g = 255;
b = 0;
}else if(num < 255 *3){
r = 0;
g = 255;
b = num - 255 * 2;
}else if(num < 255*4){
r = 0;
g = 255-(num - 255 * 3);
b = 255;
}else if(num < 255*5){
r = num - 255 * 4;
g = 0;
b = 255;
}else if(num < 255 * 6){
r = 255;
g = 0;
b = 255-(num - 255 * 5);
}
return Scalar(r,g,b);
}
int convertScalar2Num(int r,int g,int b)
{
return b * 255 * 255 + g * 255 + r-1;
}
CamShiftArea::CamShiftArea(void)
{
histimg = Mat::zeros(200, 320, CV_8UC3);
selectObject = false;
trackObject = 0;
}
CamShiftArea::CamShiftArea(int width,int height)
{
histimg = Mat::zeros(200, 320, CV_8UC3);
positionData = Mat::zeros(width, height, CV_8UC3);
selectObject = false;
trackObject = 0;
positionData = Mat::zeros(width, height, CV_8UC3);
beforeAreaNum = -1;
beforeTime = 0;
graph = Mat::zeros( 10*10*5,1200, CV_8UC3);
}
CamShiftArea::~CamShiftArea(void)
{
}
void CamShiftArea::calucurateCamShit(Mat image,int num,int nowTime,int _vmin, int _vmax ,int smin,bool backprojMode)
{//http://iwaki2009.blogspot.jp/2013/02/opencv_68.html
int hsize = 16;
float hranges[] = {0,180};
const float* phranges = hranges;
Mat hsv,mask,hue;;
cv::cvtColor(image, hsv, CV_BGR2HSV);
if( trackObject )//&& caluculatedNum < nowNum
{
/*============2 マスク画像の作成============*/
inRange(hsv,
Scalar(0, smin, MIN(_vmin,_vmax)),
Scalar(180, 256, MAX(_vmin, _vmax)),
mask);
/*============3 RGBからHSV変換し、H画像の取得============*/
int ch[] = {0, 0};
hue.create(hsv.size(), hsv.depth());
mixChannels(&hsv, 1, &hue, 1, ch, 1);
/*============4 指定エリアのヒストグラムを計算、正規化、描画============*/
if( trackObject < 0 ){
Mat roi(hue, selection), maskroi(mask, selection);
calcHist(&roi, 1, 0, maskroi, hist, 1, &hsize, &phranges);
normalize(hist, hist, 0, 255, CV_MINMAX);
trackWindow = selection;
trackObject = 1;
histimg = Scalar::all(0);
int binW = histimg.cols / hsize;
Mat buf(1, hsize, CV_8UC3);
for( int i = 0; i < hsize; i++ ){
buf.at<Vec3b>(i) = Vec3b(saturate_cast<uchar>(i*180./hsize), 255, 255);
}
cv::cvtColor(buf, buf, CV_HSV2BGR);
for( int i = 0; i < hsize; i++ ){
int val = saturate_cast<int>(hist.at<float>(i)*histimg.rows/255);
rectangle( histimg, Point(i*binW,histimg.rows),
Point((i+1)*binW,histimg.rows - val),
Scalar(buf.at<Vec3b>(i)), -1, 8 );
}
}
/*============5 ヒストグラムを元にBackProjectionを計算============*/
calcBackProject(&hue, 1, 0, hist, backproj, &phranges);
/*============6 計算結果にマスクをかける============*/
backproj &= mask;
/*============7 CamShiftにより対象エリアの計算============*/
RotatedRect trackBox = cv::CamShift(backproj, trackWindow,
TermCriteria( CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 10, 1 ));
/*============8 次回探索枠の計算============*/
if( trackWindow.area() <= 1 ){
int cols = backproj.cols, rows = backproj.rows, r = (MIN(cols, rows) + 5)/6;
trackWindow = Rect(trackWindow.x - r, trackWindow.y - r,
trackWindow.x + r, trackWindow.y + r) &
Rect(0, 0, cols, rows);
}
if( backprojMode ){
cv::cvtColor( backproj, image, CV_GRAY2BGR );
}
/*============現在エリアの探索============*/
int areaNum=this->getAreaNum(trackBox.center);
/*============チャートの描画============*/
if (areaNum != -1)
this->drawGraph(graph,num,areaNum);
/*============エリア移動時はCSVに出力============*/
if(areaNum != beforeAreaNum){
fprintf(csvFile,"%d,%d\n",areaNum,nowTime-beforeTime);
beforeTime = nowTime;
beforeAreaNum = areaNum;
}
/*============探索結果を保存============*/
CamShiftResult *result = new CamShiftResult();
result->frameNum = num;
result->trackBox = trackBox;
this->results.push_back(result);
/*============軌跡を描画============*/
if (this->results.size() > 1){
cv::line(positionData,
this->results[this->results.size()-1]->trackBox.center,
this->results[this->results.size()-2]->trackBox.center,
convertNum2Scalar(num),8,8,0);
}
}
}
int CamShiftArea::getAreaNum(Point2f p)
{
for (int i=0;i<(int)points.size()/4;i++){
int targeti = i * 4;
int vec1[2];
vec1[0] = points[targeti+1].x -points[targeti].x;
vec1[1] = points[targeti+1].y -points[targeti].y;
int vec2[2];
vec2[0] = p.x -points[targeti].x;
vec2[1] = p.y -points[targeti].y;
if (vec1[0]*vec2[0]+vec1[1]*vec2[1] > 0.0){
targeti++;
vec1[0] = points[targeti+1].x -points[targeti].x;
vec1[1] = points[targeti+1].y -points[targeti].y;
vec2[0] = p.x -points[targeti].x;
vec2[1] = p.y -points[targeti].y;
if (vec1[0]*vec2[0]+vec1[1]*vec2[1] > 0.0){
targeti++;
vec1[0] = points[targeti+1].x -points[targeti].x;
vec1[1] = points[targeti+1].y -points[targeti].y;
vec2[0] = p.x -points[targeti].x;
vec2[1] = p.y -points[targeti].y;
if (vec1[0]*vec2[0]+vec1[1]*vec2[1] > 0.0){
targeti++;
vec1[0] = points[targeti-3].x -points[targeti].x;
vec1[1] = points[targeti-3].y -points[targeti].y;
vec2[0] = p.x -points[targeti].x;
vec2[1] = p.y -points[targeti].y;
if (vec1[0]*vec2[0]+vec1[1]*vec2[1] > 0.0){
return i;
}
}
}
}
}
return -1;
}
void CamShiftArea::drawGraph(Mat graph,int time,int areaNum)
{
cv::line(graph,cvPoint(time%1200,(int)(time/1200) *10*10+ areaNum*10),cvPoint(time%1200,(int)(time/1200) *10*10+ areaNum*10+10),convertMidiumNum2Scalar(time) , 1, CV_AA, 0);
}
void CamShiftArea::drawLines(Mat image,cv::Scalar color,bool colorFlag)
{
for (int i = 1;i < results.size();i++){
if(colorFlag){
color = convertMidiumNum2Scalar(results[i]->frameNum);
cv::line(image,results[i-1]->trackBox.center,results[i]->trackBox.center,color,1,8,0);
}else{
cv::line(image,results[i-1]->trackBox.center,results[i]->trackBox.center,color,1,8,0);
}
}
}
void CamShiftArea::drawTarget(Mat image,cv::Scalar color,int num)
{
for (int i = 0;i < results.size();i++){
if(results[i]->frameNum == num){
ellipse( image, results[i]->trackBox, color, 3, CV_AA );
}
}
return;
}
void CamShiftArea::drawArea(Mat image)
{
int areaNum = 0;
for (int i = 1;i < points.size();i++){
Scalar color = convertMidiumNum2Scalar(areaNum*50);
areaNum++;
cv::line(image,points[i-1],points[i],color,3,8,0);
i++;
if(i < points.size()){
cv::line(image,points[i-1],points[i],color,3,8,0);
i++;
}
if(i < points.size()){
cv::line(image,points[i-1],points[i],color,3,8,0);
cv::line(image,points[i-3],points[i],color,3,8,0);
i++;
}
}
}
int CamShiftArea::getTimePoint(int x,int y)
{
cv::Vec3b bgr = positionData.at<cv::Vec3b>(y,x);
printf("%d,%d,%d\n",bgr[0],bgr[1],bgr[2]);
if(bgr[0] == 0 && bgr[1] == 0 && bgr[2]==0)return -1;
int num = convertScalar2Num(bgr[0],bgr[1],bgr[2]);
return num;
}
ManyCamShiftAreaDesition::ManyCamShiftAreaDesition(void)
{
backprojMode = false;
showHist = true;
vmin = 10;
vmax = 256;
smin = 30;
caluculatedNum = -1;
targetArea = -1;
}
ManyCamShiftAreaDesition::~ManyCamShiftAreaDesition(void)
{
}
void ManyCamShiftAreaDesition::startCreateArea(int x, int y)
{
origin = Point(x,y);
tmpArea = new CamShiftArea( image.rows, image.cols);
tmpArea->selection = Rect(x,y,0,0);
}
void ManyCamShiftAreaDesition::endCreateArea(int x, int y)
{
tmpArea->selection.x = MIN(x, origin.x);
tmpArea->selection.y = MIN(y, origin.y);
tmpArea->selection.width = std::abs(x - origin.x);
tmpArea->selection.height = std::abs(y - origin.y);
tmpArea->selection &= Rect(0, 0, image.cols, image.rows);
if( tmpArea->selection.width > 0 && tmpArea->selection.height > 0 ){
tmpArea->trackObject = -1;
tmpArea->beforeTime = cap.get(CV_CAP_PROP_POS_MSEC );
char hoge[256];
sprintf(hoge,"ManChart%d.csv",areas.size());
tmpArea->csvFile = fopen(hoge,"w");
targetArea = 0;
if (areas.size() == 0){
for (int i=0;i<this->tmpPoints.size();i++){
tmpArea->points.push_back(this->tmpPoints[i]);
}
}
areas.push_back(tmpArea);
}else{
delete tmpArea;
}
}
void ManyCamShiftAreaDesition::timeShift(int x, int y)
{
if(targetArea > -1 && targetArea < areas.size()){
int num = areas[targetArea]->getTimePoint(x,y);
if (num > 0)cap.set(CV_CAP_PROP_POS_FRAMES ,(double)num);
}
}
void ManyCamShiftAreaDesition::createWork(int x,int y)
{
areas[targetArea]->points.push_back(cvPoint(x,y));
}
void ManyCamShiftAreaDesition::mouseEvent (int event, int x, int y, int flags, void *param)
{
switch( event )
{
case CV_EVENT_LBUTTONDOWN:
this->startCreateArea(x,y);
break;
case CV_EVENT_LBUTTONUP:
this->endCreateArea(x,y);
break;
case CV_EVENT_RBUTTONUP:
if (flags & CV_EVENT_FLAG_ALTKEY){
this->timeShift(x,y);
}else{
this->createWork(x,y);
}
break;
}
}
void ManyCamShiftAreaDesition::keyEvent(char c)
{
switch(c){
case 'b':
backprojMode = !backprojMode;
break;
case 'h':
showHist = !showHist;
if( !showHist )
destroyWindow( "Histogram" );
else
namedWindow( "Histogram", 1 );
break;
case 'p':
paused = !paused;
break;
case 'n': //←
targetArea--;
if (targetArea == -1){
targetArea = areas.size()-1;
}
break;
case 'm': //⇒
targetArea++;
if (areas.size() == targetArea){
targetArea = 0;
}
break;
case 's':
cv::imwrite("hoge.jpg",image);
cv::imwrite("positionData.jpg",positionData);
break;
case 'q':
cv::imwrite("positionData.jpg",positionData);
break;
case 'z':
areas.pop_back();
break;
default:
break;
}
}
void ManyCamShiftAreaDesition::drawNowPoint(Mat graph,int time)
{
cv::line(graph,cvPoint(time%1200,(int)(time/1200) *10*10+ 0),cvPoint(time%1200,(int)(time/1200) *10*10+ 100),Scalar(255,255,255) , 1, CV_AA, 0);
}
void ManyCamShiftAreaDesition::init(void)
{
FILE *initfp;
initfp = fopen("ini/CamShift.txt", "r");
char fileName[256];
int mode;
fscanf(initfp,"%d",&mode);
if (mode == 1){
fscanf(initfp,"%s",&fileName);
fscanf(initfp,"%d",&speed);
this->cap.open(fileName);
int areaNum;
fscanf(initfp,"%d",&areaNum);
for(int i=0;i<areaNum;i++){
for(int j=0;j<4;j++){
int x,y;
fscanf(initfp,"%d",&x);
fscanf(initfp,"%d",&y);
this->tmpPoints.push_back(cvPoint(x,y));
}
}
}else{
cap.open(0);
}
cvNamedWindow( "Capture", 1 );
cvSetMouseCallback ("Capture", on_mouse);
}
void ManyCamShiftAreaDesition::mainloop(void)
{
Rect trackWindow;
int hsize = 16;
float hranges[] = {0,180};
const float* phranges = hranges;
this->waitSprrd = 10;
namedWindow( "Histogram", 0 );
createTrackbar( "Vmin", "Capture", &vmin, 256, 0 );
createTrackbar( "Vmax", "Capture", &vmax, 256, 0 );
createTrackbar( "Smin", "Capture", &smin, 256, 0 );
createTrackbar( "SkipSpeed", "Capture", &speed, 10, 0 );
createTrackbar( "WaitSpeed", "Capture", &this->waitSprrd, 50, 0 );
Mat frame, histimg = Mat::zeros(200, 320, CV_8UC3),backproj,hist;
paused = true;
cap >> frame;
frame.copyTo(positionData);
speed = 1;
for(;;)
{
if( !paused )
{
cap >> frame;
for(int i=0;i<speed;i++){
cap >> frame;
}
if( frame.empty() ){
break;
}
}
frame.copyTo(image);
int nowNum = cap.get(CV_CAP_PROP_POS_FRAMES );
int nowTime = cap.get(CV_CAP_PROP_POS_MSEC );
if( !paused ){
if( caluculatedNum < nowNum){
for (int i=0;i<this->areas.size();i++){
areas[i]->calucurateCamShit(image,nowNum,nowTime,vmin,vmax,smin,backprojMode);
}
caluculatedNum = nowNum;
}
}
if( this->areas.size() > 0 ){
paused = false;
}
for (int i=0;i<this->areas.size();i++) {
if (targetArea == i){
areas[i]->drawLines(image,convertSmallNum2Scalar(i),true);
areas[i]->drawArea(image);
Mat showGraph = areas[i]->graph.clone();
this->drawNowPoint(showGraph,nowNum);
imshow( "Graph", showGraph );
}else{
areas[i]->drawLines(image,convertSmallNum2Scalar(i),false);
}
areas[i]->drawTarget(image,convertSmallNum2Scalar(i),nowNum);
}
imshow( "Capture", image );
imshow( "Histogram", histimg );
if (this->waitSprrd == 0)this->waitSprrd=1;
char c = (char)waitKey(this->waitSprrd);
if( c == 27 ){
cv::imwrite("positionData.jpg",positionData);
for (int i=0;i<this->areas.size();i++) {
char hoge[256];
sprintf(hoge,"metyo%d.jpg",i);
cv::imwrite(hoge,this->areas[i]->positionData);
fclose(areas[i]->csvFile);
}
break;
}
this->keyEvent(c);
}
}
void ManyCamShiftAreaDesition::term(void)
{
}
0 件のコメント:
コメントを投稿