失礼致しました。
書き直したソースコードとコンパイル時に出たエラーを載せます。
コード:
// block.h
#ifndef __BLOCK_H__
#define __BLOCK_H__
#include <stdlib.h>
template <class Type> class Block
{
public:
Block(int size, void (*err_function)(char *) = NULL) {
first = last = NULL;
block_size = size;
error_function = err_function;
}
~Block() {
while (first) {
block *next = first -> next;
delete[] ((char *)first);
first = next;
}
}
Type *New(int num = 1) {
Type *t;
if (!last || last->current + num > last->last) {
if (last && last->next) {
last = last->next;
}
else {
block *next = (block *)new char [sizeof(block) + (block_size-1) * sizeof(Type)];
if (!next) {
if (error_function) {
(*error_function)("Not enough memory!");
exit(1);
}
}
if (last) {
last->next = next;
}
else {
first = next;
}
last = next;
last->current = & (last->data[0]);
last->last = last->current + block_size;
last->next = NULL;
}
}
t = last->current;
last->current += num;
return t;
}
Type *ScanFirst() {
for (scan_current_block = first; scan_current_block; scan_current_block = scan_current_block->next) {
scan_current_data = & (scan_current_block->data[0]);
if (scan_current_data < scan_current_block->current) {
return scan_current_data++;
}
}
return NULL;
}
Type *ScanNext() {
while (scan_current_data >= scan_current_block->current) {
scan_current_block = scan_current_block->next;
if (!scan_current_block) {
return NULL;
}
scan_current_data = & (scan_current_block->data[0]);
}
return scan_current_data++;
}
void Reset() {
block *b;
if (!first) {
return;
}
for (b = first; ; b = b->next) {
b->current = & (b->data[0]);
if (b == last) {
break;
}
}
last = first;
}
private:
typedef struct block_st {
Type *current, *last;
struct block_st *next;
Type data[1];
} block;
int block_size;
block *first;
block *last;
block *scan_current_block;
Type *scan_current_data;
void (*error_function)(char *);
};
template <class Type> class DBlock
{
public:
DBlock(int size, void (*err_function)(char *) = NULL) {
first = NULL;
first_free = NULL;
block_size = size;
error_function = err_function;
}
~DBlock() {
while (first) {
block *next = first->next;
delete[] ((char*)first);
first = next;
}
}
Type *New() {
block_item *item;
if (!first_free) {
block *next = first;
first = (block *) new char [sizeof(block) + (block_size - 1) * sizeof(block_item)];
if (!first) {
if (error_function) {
(*error_function)("Not enough memory!");
exit(1);
}
}
first_free = &(first->data[0]);
for (item = first_free; item < first_free + block_size - 1; item++)
item->next_free = item + 1;
item->next_free = NULL;
first->next = next;
}
item = first_free;
first_free = item->next_free;
return (Type *)item;
}
void Delete(Type *t) {
((block_item *)t)->next_free = first_free;
first_free = (block_item *)t;
}
private:
typedef union block_item_st {
Type t;
block_item_st *next_free;
} block_item;
typedef struct block_st {
struct block_st *next;
block_item data[1];
} block;
int block_size;
block *first;
block_item *first_free;
void (*error_function)(char *);
};
#endif
コード:
// GCApplication.h
#include <iostream>
#include <fstream>
#include <cmath>
#include "graph.h"
#include "opencv/cv.h"
#include "opencv/highgui.h"
#include "GMM.h"
using namespace cv;
using namespace std;
class GCApplication {
public:
enum {
NOT_SET = 0,
IN_PROCESS = 1,
SET = 2,
LBUTTON = 3,
RBUTTON = 4,
BGR = 5,
HSV = 6
};
static const int thickness = -1;
int radius;
double lambda;
void MouseClick(int event, int x, int y, int flags, void *param);
void SetImageAndWinName(const Mat &_image, const string &_winName);
void ShowImage() const;
void Reset();
void GraphCut();
private:
const string *winName;
const Mat *image;
Mat mask;
int width;
int height;
double beta;
double maxCap;
vector<Point> foregroundPixels, backgroundPixels;
bool isInitialized;
bool isCreateGraph;
uchar labelsState;
typedef Graph<double, double, double> GraphType;
GraphType *graph;
void SetLblsInMask(uchar flag, Point p);
double CalcBeta(const Mat &img);
void CreateGraph();
double CalcNLink(Point p);
double NeighborWeight(Point x, Point y);
void SetTLink(GMM fgdGMM, GMM bgdGMM);
void Init();
void CreateMask();
Mat bgdModel, fgdModel;
void InitGMMs(const Mat &img, const Mat &mask, GMM &bgdGMM, GMM &fgdGMM);
void AssignGMMsComponents(const Mat &img, const Mat &mask, const GMM &bgdGMM, const GMM &fgdGMM, Mat &compIdxs);
void LearnGMMs(const Mat &img, const Mat &mask, const Mat &compIdxs, GMM &bgdGMM, GMM &fgdGMM);
};
コード:
// GMM.h
#include <iostream>
#include "graph.h"
#include "opencv/cv.h"
#include "opencv/highgui.h"
using namespace cv;
using namespace std;
class GMM
{
public:
static const int componentsCount = 5;
GMM(Mat &_model);
float operator()(Vec3f color) const;
float operator()(int ci, Vec3f color) const;
int WhichComponent(Vec3f color) const;
void InitLearning();
void AddSample(int ci, Vec3f color);
void EndLearning();
private:
void CalcInverseCovAndDeterm(int ci);
Mat model;
float *coefs;
float *mean;
float *cov;
float inverseCovs[componentsCount][3][3];
float covDeterms[componentsCount];
float sums[componentsCount][3];
float prods[componentsCount][3][3];
int sampleCounts[componentsCount];
int totalSampleCount;
};
コード:
// graph.h
#ifndef __GRAPH_H__
#define __GRAPH_H__
#include <string.h>
#include <assert.h>
#include "block.h"
template <typename captype, typename tcaptype, typename flowtype> class Graph
{
public:
typedef enum {
SOURCE = 0,
SINK = 1
} termtype;
typedef int node_id;
Graph(int node_num_max, int edge_num_max, void (*err_function)(char *) = NULL);
~Graph();
node_id add_node(int num = 1);
void add_edge(node_id i, node_id j, captype cap, captype rev_cap);
void add_tweights(node_id i, tcaptype cap_source, tcaptype cap_sink);
flowtype maxflow(bool reuse_trees = false, Block<node_id> *changed_list = NULL);
termtype what_segment(node_id i, termtype default_segm = SOURCE);
private:
struct node;
struct arc;
public:
void reset();
typedef arc *arc_id;
arc_id get_first_arc();
arc_id get_next_arc(arc_id a);
int get_node_num() {
return node_num;
}
int get_arc_num() {
return (int)(arc_last - arcs);
}
void get_arc_ends(arc_id a, node_id &i, node_id &j);
tcaptype get_trcap(node_id i);
captype get_rcap(arc *a);
void set_trcap(node_id i, tcaptype trcap);
void set_rcap(arc *a, captype rcap);
void mark_node(node_id i);
void remove_from_changed_list(node_id i) {
assert(i >= 0 && i<node_num && nodes[i].is_in_changed_list);
nodes[i].is_in_changed_list = 0;
}
private:
struct node {
arc *first;
arc *parent;
node *next;
int TS;
int DIST;
int is_sink : 1;
int is_marked : 1;
int is_in_changed_list : 1;
tcaptype tr_cap;
};
struct arc {
node *head;
arc *next;
arc *sister;
captype r_cap;
};
struct nodeptr {
node *ptr;
nodeptr *next;
};
static const int NODEPTR_BLOCK_SIZE = 128;
node *nodes, *node_last, *node_max;
arc *arcs, *arc_last, *arc_max;
int node_num;
DBlock<nodeptr> *nodeptr_block;
void (*error_function)(char *);
flowtype flow;
int maxflow_iteration;
Block<node_id> *changed_list;
node *queue_first[2], *queue_last[2];
nodeptr *orphan_first, *orphan_last;
int TIME;
void reallocate_nodes(int num);
void reallocate_arcs();
void set_active(node *i);
node *next_active();
void set_orphan_front(node *i);
void set_orphan_rear(node *i);
void add_to_changed_list(node *i);
void maxflow_init();
void maxflow_reuse_trees_init();
void augment(arc *middle_arc);
void process_source_orphan(node *i);
void process_sink_orphan(node *i);
void test_consistency(node *current_node = NULL);
};
template <typename captype, typename tcaptype, typename flowtype> inline typename Graph<captype, tcaptype, flowtype>::node_id Graph<captype, tcaptype, flowtype>::add_node(int num)
{
assert(num > 0);
if (node_last + num > node_max) {
reallocate_nodes(num);
}
if (num == 1) {
node_last->first = NULL;
node_last->tr_cap = 0;
node_last->is_marked = 0;
node_last->is_in_changed_list = 0;
node_last++;
return node_num++;
}
else {
memset(node_last, 0, num * sizeof(node));
node_id i = node_num;
node_num += num;
node_last += num;
return i;
}
}
template <typename captype, typename tcaptype, typename flowtype> inline void Graph<captype, tcaptype, flowtype>::add_tweights(node_id i, tcaptype cap_source, tcaptype cap_sink)
{
assert(i >= 0 && i < node_num);
tcaptype delta = nodes[i].tr_cap;
if (delta > 0) {
cap_source += delta;
}
else {
cap_sink -= delta;
}
flow += (cap_source < cap_sink) ? cap_source : cap_sink;
nodes[i].tr_cap = cap_source - cap_sink;
}
template <typename captype, typename tcaptype, typename flowtype> inline void Graph<captype, tcaptype, flowtype>::add_edge(node_id _i, node_id _j, captype cap, captype rev_cap)
{
assert(_i >= 0 && _i < node_num);
assert(_j >= 0 && _j < node_num);
assert(_i != _j);
assert(cap >= 0);
assert(rev_cap >= 0);
if (arc_last == arc_max) {
reallocate_arcs();
}
arc *a = arc_last++;
arc *a_rev = arc_last++;
node *i = nodes + _i;
node *j = nodes + _j;
a->sister = a_rev;
a_rev->sister = a;
a->next = i->first;
i->first = a;
a_rev->next = j->first;
j->first = a_rev;
a->head = j;
a_rev->head = i;
a->r_cap = cap;
a_rev->r_cap = rev_cap;
}
template <typename captype, typename tcaptype, typename flowtype> inline typename Graph<captype, tcaptype, flowtype>::arc *Graph<captype, tcaptype, flowtype>::get_first_arc()
{
return arcs;
}
template <typename captype, typename tcaptype, typename flowtype> inline typename Graph<captype, tcaptype, flowtype>::arc *Graph<captype, tcaptype, flowtype>::get_next_arc(arc *a)
{
return a + 1;
}
template <typename captype, typename tcaptype, typename flowtype> inline void Graph<captype, tcaptype, flowtype>::get_arc_ends(arc *a, node_id &i, node_id &j)
{
assert(a >= arcs && a < arc_last);
i = (node_id) (a->sister->head - nodes);
j = (node_id) (a->head - nodes);
}
template <typename captype, typename tcaptype, typename flowtype> inline tcaptype Graph<captype, tcaptype, flowtype>::get_trcap(node_id i)
{
assert(i >= 0 && i < node_num);
return nodes[i].tr_cap;
}
template <typename captype, typename tcaptype, typename flowtype> inline captype Graph<captype, tcaptype, flowtype>::get_rcap(arc *a)
{
assert(a >= arcs && a < arc_last);
return a->r_cap;
}
template <typename captype, typename tcaptype, typename flowtype> inline void Graph<captype, tcaptype, flowtype>::set_trcap(node_id i, tcaptype trcap)
{
assert(i >= 0 && i < node_num);
nodes[i].tr_cap = trcap;
}
template <typename captype, typename tcaptype, typename flowtype> inline void Graph<captype, tcaptype, flowtype>::set_rcap(arc *a, captype rcap)
{
assert(a >= arcs && a < arc_last);
a->r_cap = rcap;
}
template <typename captype, typename tcaptype, typename flowtype> inline typename Graph<captype, tcaptype, flowtype>::termtype Graph<captype, tcaptype, flowtype>::what_segment(node_id i, termtype default_segm)
{
if (nodes[i].parent) {
return (nodes[i].is_sink) ? SINK : SOURCE;
}
else {
return default_segm;
}
}
template <typename captype, typename tcaptype, typename flowtype> inline void Graph<captype, tcaptype, flowtype>::mark_node(node_id _i)
{
node *i = nodes + _i;
if (!i->next) {
if (queue_last[1]) {
queue_last[1]->next = i;
}
else {
queue_first[1] = i;
}
queue_last[1] = i;
i->next = i;
}
i->is_marked = 1;
}
#endif
コード:
// Histgram.h
#include <iostream>
#include "graph.h"
#include "opencv/cv.h"
#include "opencv/highgui.h"
using namespace cv;
using namespace std;
class Histgram {
public:
Histgram();
void CreateHistrgram(const Mat img, Mat mask);
float operator()(Vec3f color) const;
private:
MatND histgram;
int bins;
float sum;
};
コード:
// instances.inc
#include "graph.h"
#ifdef _MSC_VER
#pragma warning(disable: 4661)
#endif
template class Graph<int, int, int>;
template class Graph<short, int, int>;
template class Graph<float, float, float>;
template class Graph<double, double, double>;
コード:
// GCApplication.cpp
#include <stdint.h>
#include "GCApplication.h"
const Scalar RED = Scalar(0, 0, 255);
const Scalar PINK = Scalar(230, 130, 255);
const Scalar BLUE = Scalar(255, 0, 0);
const Scalar LIGHTBLUE = Scalar(255, 255, 160);
const Scalar GREEN = Scalar(0, 255, 0);
void getBinMask(const Mat &comMask, Mat &binMask)
{
if (comMask.empty() || comMask.type() != CV_8UC1) {
CV_Error(CV_StsBadArg, "comMask is empty or has incorrect type (not CV_8UC1)");
}
if (binMask.empty() || binMask.rows != comMask.rows || binMask.cols != comMask.cols) {
binMask.create(comMask.size(), CV_8UC1);
}
binMask = comMask & 1;
}
void GCApplication::MouseClick(int event, int x, int y, int flags, void *param)
{
vector<Point> *bpxls, *fpxls;
bpxls = &backgroundPixels;
fpxls = &foregroundPixels;
switch (event) {
case CV_EVENT_LBUTTONDOWN:
labelsState = LBUTTON;
break;
case CV_EVENT_LBUTTONUP:
if (labelsState == LBUTTON) {
SetLblsInMask(LBUTTON, Point(x, y));
ShowImage();
}
labelsState = SET;
break;
case CV_EVENT_RBUTTONDOWN:
labelsState = RBUTTON;
break;
case CV_EVENT_RBUTTONUP:
if (labelsState == RBUTTON) {
SetLblsInMask(RBUTTON, Point(x, y));
ShowImage();
}
labelsState = SET;
break;
case CV_EVENT_MOUSEMOVE:
if (labelsState == LBUTTON) {
SetLblsInMask(LBUTTON, Point(x, y));
ShowImage();
}
else if(labelsState == RBUTTON) {
SetLblsInMask(RBUTTON, Point(x, y));
ShowImage();
}
break;
}
}
void GCApplication::Reset()
{
if (!mask.empty()) {
mask.setTo(Scalar::all(GC_PR_BGD));
}
foregroundPixels.clear();
backgroundPixels.clear();
fgdModel = bgdModel = NULL;
isInitialized = false;
delete graph;
isCreateGraph = false;
mask.setTo(Scalar(GC_PR_BGD));
CreateGraph();
}
void GCApplication::Init()
{
lambda = 2;
radius = 3;
width = image->cols;
height = image->rows;
mask.create(image->size(), CV_8UC1);
}
void GCApplication::SetImageAndWinName(const Mat &_image, const string &_winName)
{
if (_image.empty() || _winName.empty()) {
return;
}
image = &_image;
winName = &_winName;
Init();
Reset();
}
void GCApplication::SetLblsInMask(uchar flag, Point p)
{
if (flag == RBUTTON) {
backgroundPixels.push_back(p);
circle(mask, p, radius, GC_BGD, thickness);
}
if (flag == LBUTTON) {
foregroundPixels.push_back(p);
circle(mask, p, radius, GC_FGD, thickness);
}
}
void GCApplication::ShowImage() const
{
if (image->empty() || winName->empty()) {
return;
}
Mat res;
Mat binMask;
if (isInitialized == true) {
getBinMask(mask, binMask);
image->copyTo(res, binMask);
}
else {
image->copyTo(res);
}
vector<Point>::const_iterator iterator;
for (iterator = foregroundPixels.begin(); iterator != foregroundPixels.end(); iterator++) {
circle(res, *iterator, radius, RED, thickness);
}
for (iterator = backgroundPixels.begin(); iterator != backgroundPixels.end(); iterator++) {
circle(res, *iterator, radius, BLUE, thickness);
}
imshow(*winName, res);
}
void GCApplication::CreateGraph()
{
if (image->empty()) {
return ;
}
cout << "now create graph";
maxCap = -1;
if (isCreateGraph == false) {
int vertexNum = width * height;
graph = new GraphType(vertexNum, vertexNum * 4);
graph->add_node(vertexNum);
beta = CalcBeta(*image);
double sumCap;
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
sumCap = CalcNLink(Point(j, i));
if (maxCap < sumCap) {
maxCap = sumCap;
}
}
}
maxCap *= 9.0;
}
cout << "...end" << endl;
isCreateGraph = true;
}
double GCApplication::CalcNLink(Point p)
{
double cap;
double sumCap = 0.0;
int width = image->cols;
int height = image->rows;
if (p.x - 1 >= 0) {
cap = NeighborWeight(p, Point(p.x - 1, p.y));
sumCap += cap;
graph->add_edge((p.y * width) + p.x, (p.y * width) + p.x - 1, cap, cap);
if (p.y - 1 >= 0) {
cap = NeighborWeight(p, Point(p.x - 1, p.y - 1 )) * 0.707106781;
sumCap += cap;
graph->add_edge((p.y * width) + p.x, ((p.y -1) * width) + p.x - 1, cap, cap);
}
}
if (p.x + 1 < width) {
if (p.y - 1 >= 0) {
cap = NeighborWeight(p, Point(p.x + 1, p.y - 1)) * 0.707106781;
sumCap += cap;
graph->add_edge((p.y * width) + p.x, ((p.y - 1) * width) + p.x + 1, cap, cap);
}
}
if (p.y - 1 >= 0) {
cap = NeighborWeight(p, Point(p.x, p.y - 1));
sumCap += cap;
graph->add_edge((p.y * width) + p.x, ((p.y - 1 ) * width) + p.x, cap, 0);
}
return sumCap * 2;
}
double GCApplication::NeighborWeight(Point x, Point y)
{
Vec3f x_BGR = image->at<Vec3b>(x);
Vec3f y_BGR = image->at<Vec3b>(y);
Vec3f diff = x_BGR - y_BGR;
double distance = diff.dot(diff);
return (500.0 * exp(-distance * beta));
}
double GCApplication::CalcBeta(const Mat &img)
{
double beta = 0;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
Vec3f color = img.at<Vec3b>(y, x);
if (x > 0) {
Vec3f diff = color - (Vec3f)img.at<Vec3b>(y, x - 1);
beta += diff.dot(diff);
}
if (y > 0 && x > 0) {
Vec3f diff = color - (Vec3f)img.at<Vec3b>(y - 1, x - 1);
beta += diff.dot(diff);
}
if (y > 0) {
Vec3f diff = color - (Vec3f)img.at<Vec3b>(y - 1, x);
beta += diff.dot(diff);
}
if (y > 0 && x < img.cols - 1) {
Vec3f diff = color - (Vec3f)img.at<Vec3b>(y - 1, x + 1);
beta += diff.dot(diff);
}
}
}
beta = 1.f / (2 * beta / (4 * img.cols * img.rows - 3 * img.cols - 3 * img.rows + 2));
return beta;
}
void GCApplication::SetTLink(GMM fgdGMM, GMM bgdGMM)
{
double fromSource;
double toSink;
Vec3f color;
Point p;
for (p.y = 0; p.y < height; ++p.y) {
for (p.x = 0; p.x < width; ++p.x) {
int node_id = p.y * width + p.x;
if (mask.at<uchar>(p) == GC_BGD) {
fromSource = 0.0;
toSink = maxCap;
}
else if (mask.at<uchar>(p) == GC_FGD) {
fromSource = maxCap;
toSink = 0.0;
}
else {
color = (Vec3f)image->at<Vec3b>(p);
fromSource = -log(bgdGMM(color));
toSink = -log(fgdGMM(color));
fromSource *= lambda;
toSink *= lambda;
}
graph->add_tweights(node_id, fromSource, toSink);
}
}
}
void GCApplication::CreateMask()
{
Point p;
for (p.y = 0; p.y < height; ++p.y) {
const uchar *t = mask.ptr(p.y);
for (p.x = 0; p.x < width; ++p.x) {
uchar flag = t[p.x];
if (flag == GC_PR_FGD || flag == GC_PR_BGD) {
if (graph->what_segment(p.y * width+p.x) == GraphType::SOURCE) {
mask.at<uchar>(p) = GC_PR_FGD;
}
else if (graph->what_segment(p.y * width + p.x) == GraphType::SINK) {
mask.at<uchar>(p) = GC_PR_BGD;
}
}
}
}
}
void GCApplication::GraphCut()
{
if (!isInitialized && (foregroundPixels.empty() || backgroundPixels.empty() )) {
cout << "seedを指定していください" << endl;
return;
}
uint64_t appStart = getTickCount();
GMM bgdGMM(bgdModel);
GMM fgdGMM(fgdModel);
if (lambda != 0) {
cout << "now Calc GMM";
Mat compIdxs(image->size(), CV_32SC1);
cout << ".";
InitGMMs(*image, mask, bgdGMM, fgdGMM);
cout << ".";
AssignGMMsComponents(*image, mask, bgdGMM, fgdGMM, compIdxs);
cout << ".";
LearnGMMs(*image, mask, compIdxs, bgdGMM, fgdGMM);
cout << ".GMM終わり" << endl;
}
cout << "--- now start GraphCut ---" << endl;
SetTLink(fgdGMM, bgdGMM);
uint64_t start = getTickCount();
double maxflowValue = graph->maxflow();
CreateMask();
backgroundPixels.clear();
foregroundPixels.clear();
isInitialized = true;
ShowImage();
}
void GCApplication::InitGMMs(const cv::Mat &img, const cv::Mat &mask, GMM &bgdGMM, GMM &fgdGMM)
{
const int kMeansItCount = 10;
const int kMeansType = KMEANS_PP_CENTERS;
Mat bgdLabels;
Mat fgdLabels;
vector<Vec3f> bgdSamples, fgdSamples;
Point p;
for (p.y = 0; p.y < height; p.y++) {
for (p.x = 0; p.x < width; p.x++) {
if (mask.at<uchar>(p) == GC_BGD || mask.at<uchar>(p) == GC_PR_BGD) {
bgdSamples.push_back((Vec3f)img.at<Vec3b>(p));
}
else {
fgdSamples.push_back((Vec3f)img.at<Vec3b>(p));
}
}
}
CV_Assert(!bgdSamples.empty() && !fgdSamples.empty());
Mat _bgdSamples((int)bgdSamples.size(), 3, CV_32FC1, &bgdSamples[0][0]);
kmeans(_bgdSamples, GMM::componentsCount, bgdLabels, TermCriteria(CV_TERMCRIT_ITER, kMeansItCount, 0.0), 0, kMeansType, 0);
Mat _fgdSamples((int)fgdSamples.size(), 3, CV_32FC1, &fgdSamples[0][0]);
kmeans(_fgdSamples, GMM::componentsCount, fgdLabels, TermCriteria(CV_TERMCRIT_ITER, kMeansItCount, 0.0), 0, kMeansType, 0);
bgdGMM.InitLearning();
for (int i = 0; i < (int)bgdSamples.size(); i++) {
bgdGMM.AddSample(bgdLabels.at<int>(i, 0), bgdSamples[i]);
}
bgdGMM.EndLearning();
fgdGMM.InitLearning();
for (int i = 0; i < (int)fgdSamples.size(); i++) {
fgdGMM.AddSample(fgdLabels.at<int>(i, 0), fgdSamples[i]);
}
fgdGMM.EndLearning();
}
void GCApplication::AssignGMMsComponents(const Mat &img, const Mat &mask, const GMM &bgdGMM, const GMM &fgdGMM, Mat &compIdxs)
{
Point p;
for (p.y = 0; p.y < height; p.y++) {
for (p.x = 0; p.x < width; p.x++) {
Vec3f color = img.at<Vec3b>(p);
compIdxs.at<int>(p) = mask.at<uchar>(p) == GC_BGD || mask.at<uchar>(p) == GC_PR_BGD ? bgdGMM.WhichComponent(color) : fgdGMM.WhichComponent(color);
}
}
}
void GCApplication::LearnGMMs(const Mat &img, const Mat &mask, const Mat &compIdxs, GMM &bgdGMM, GMM &fgdGMM)
{
bgdGMM.InitLearning();
fgdGMM.InitLearning();
Point p;
for (int ci = 0; ci < GMM::componentsCount; ci++) {
for (p.y = 0; p.y < height; p.y++) {
for (p.x = 0; p.x < width; p.x++) {
if (compIdxs.at<int>(p) == ci) {
if (mask.at<uchar>(p) == GC_BGD || mask.at<uchar>(p) == GC_PR_BGD) {
bgdGMM.AddSample(ci, img.at<Vec3b>(p));
}
else {
fgdGMM.AddSample(ci, img.at<Vec3b>(p));
}
}
}
}
}
bgdGMM.EndLearning();
fgdGMM.EndLearning();
}
コード:
// GMM.cpp
#include <limits>
#include "GMM.h"
using namespace cv;
GMM::GMM(Mat &_model)
{
const int modelSize = 3 + 9 + 1;
if (_model.empty()) {
_model.create(1, modelSize*componentsCount, CV_32FC1);
_model.setTo(Scalar(0));
}
else if((_model.type() != CV_32FC1) || (_model.rows != 1) || (_model.cols != modelSize * componentsCount)) {
std::cout << "test" << std::endl;
CV_Error(CV_StsBadArg, "_model must have CV_32FC1 type, rows == 1 and cols == 13 * componentsCount");
}
model = _model;
coefs = model.ptr<float>(0);
mean = coefs + componentsCount;
cov = mean + 3 * componentsCount;
for (int ci = 0; ci < componentsCount; ci++) {
if (coefs[ci] > 0) {
CalcInverseCovAndDeterm(ci);
}
}
}
float GMM::operator ()(Vec3f color) const
{
float res = 0;
for (int ci = 0; ci < componentsCount; ci++) {
res += coefs[ci] * (*this)(ci, color);
}
return res;
}
float GMM::operator ()(int ci, Vec3f color) const
{
float res = 0;
if (coefs[ci] > 0) {
if (covDeterms[ci] > std::numeric_limits<float>::epsilon()) {
Vec3f diff = color;
float *m = mean + 3 * ci;
diff[0] -= m[0];
diff[1] -= m[1];
diff[2] -= m[2];
float mult = diff[0] * (diff[0] * inverseCovs[ci][0][0] + diff[1] * inverseCovs[ci][1][0] + diff[2] * inverseCovs[ci][2][0]) + diff[1] * (diff[0] * inverseCovs[ci][0][1] + diff[1] * inverseCovs[ci][1][1] + diff[2] * inverseCovs[ci][2][1]) + diff[2] * (diff[0] * inverseCovs[ci][0][2] + diff[1] * inverseCovs[ci][1][2] + diff[2] * inverseCovs[ci][2][2]);
res = 1.0f / sqrt(covDeterms[ci]) * exp(-0.5f * mult);
}
}
return res;
}
int GMM::WhichComponent(Vec3f color) const
{
int k = 0;
float max = 0;
for (int ci = 0; ci < componentsCount; ci++) {
float p = (*this)(ci, color);
if (p > max) {
k = ci;
max = p;
}
}
return k;
}
void GMM::InitLearning()
{
for (int ci = 0; ci < componentsCount; ci++) {
sums[ci][0] = sums[ci][1] = sums[ci][2] = 0;
prods[ci][0][0] = prods[ci][0][1] = prods[ci][0][2] = 0;
prods[ci][1][0] = prods[ci][1][1] = prods[ci][1][2] = 0;
prods[ci][2][0] = prods[ci][2][1] = prods[ci][2][2] = 0;
sampleCounts[ci] = 0;
}
totalSampleCount = 0;
}
void GMM::AddSample(int ci, cv::Vec3f color)
{
sums[ci][0] += color[0];
sums[ci][1] += color[1];
sums[ci][2] += color[2];
prods[ci][0][0] += color[0] * color[0];
prods[ci][0][1] += color[0] * color[1];
prods[ci][0][2] += color[0] * color[2];
prods[ci][1][0] += color[1] * color[0];
prods[ci][1][1] += color[1] * color[1];
prods[ci][1][2] += color[1] * color[2];
prods[ci][2][0] += color[2] * color[0];
prods[ci][2][1] += color[2] * color[1];
prods[ci][2][2] += color[2] * color[2];
sampleCounts[ci]++;
totalSampleCount++;
}
void GMM::EndLearning()
{
for (int ci = 0; ci < componentsCount; ci++) {
int n = sampleCounts[ci];
if (n == 0) {
coefs[ci] = 0;
}
else {
coefs[ci] = (float)n / totalSampleCount;
float *m = mean + 3 * ci;
m[0] = sums[ci][0] / n;
m[1] = sums[ci][1] / n;
m[2] = sums[ci][2] / n;
float *c = cov + 9 * ci;
c[0] = prods[ci][0][0] / n - m[0] * m[0];
c[1] = prods[ci][0][1] / n - m[0] * m[1];
c[2] = prods[ci][0][2] / n - m[0] * m[2];
c[3] = prods[ci][1][0] / n - m[1] * m[0];
c[4] = prods[ci][1][1] / n - m[1] * m[1];
c[5] = prods[ci][1][2] / n - m[1] * m[2];
c[6] = prods[ci][2][0] / n - m[2] * m[0];
c[7] = prods[ci][2][1] / n - m[2] * m[1];
c[8] = prods[ci][2][2] / n - m[2] * m[2];
CalcInverseCovAndDeterm(ci);
}
}
}
void GMM::CalcInverseCovAndDeterm(int ci)
{
if (coefs[ci] > 0) {
float *c = cov + 9 * ci;
float dtrm = covDeterms[ci] = c[0] * (c[4] * c[8] - c[5] * c[7]) - c[1] * (c[3] * c[8] - c[5] * c[6]) + c[2] * (c[3] * c[7] - c[4] * c[6]);
if (dtrm > std::numeric_limits<float>::epsilon()) {
inverseCovs[ci][0][0] = (c[4] * c[8] - c[5] * c[7]) / dtrm;
inverseCovs[ci][1][0] = -(c[3] * c[8] - c[5] * c[6]) / dtrm;
inverseCovs[ci][2][0] = (c[3] * c[7] - c[4] * c[6]) / dtrm;
inverseCovs[ci][0][1] = -(c[1] * c[8] - c[2] * c[7]) / dtrm;
inverseCovs[ci][1][1] = (c[0] * c[8] - c[2] * c[6]) / dtrm;
inverseCovs[ci][2][1] = -(c[0] * c[7] - c[1] * c[6]) / dtrm;
inverseCovs[ci][0][2] = (c[1] * c[5] - c[2] * c[4]) / dtrm;
inverseCovs[ci][1][2] = -(c[0] * c[5] - c[2] * c[3]) / dtrm;
inverseCovs[ci][2][2] = (c[0] * c[4] - c[1] * c[3]) / dtrm;
}
}
}
コード:
// graph.cpp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include "graph.h"
#include "instances.inc"
using namespace std;
template <typename captype, typename tcaptype, typename flowtype> Graph<captype, tcaptype, flowtype>::Graph(int node_num_max, int edge_num_max, void (*err_function)(char *)) : node_num(0), nodeptr_block(NULL), error_function(err_function)
{
if (node_num_max < 16) {
node_num_max = 16;
}
if (edge_num_max < 16) {
edge_num_max = 16;
}
#if DEBUG
cout << "size of node : " << sizeof(node) << endl;
cout << "size of edge : " << sizeof(arc) << endl;
cout << "size of nodes : " << node_num_max * sizeof(node) / 1000000 << endl;
cout << "size of edges : " << 2 * edge_num_max * sizeof(arc) / 1000000 << endl;
#endif
nodes = (node *)malloc(node_num_max * sizeof(node));
arcs = (arc *)malloc(2 * edge_num_max * sizeof(arc));
if (!nodes || !arcs) {
if (error_function) {
(*error_function)("Not enough memory!");
exit(1);
}
}
node_last = nodes;
node_max = nodes + node_num_max;
arc_last = arcs;
arc_max = arcs + 2 * edge_num_max;
maxflow_iteration = 0;
flow = 0;
}
template <typename captype, typename tcaptype, typename flowtype> Graph<captype, tcaptype, flowtype>::~Graph()
{
if (nodeptr_block) {
delete nodeptr_block;
nodeptr_block = NULL;
}
free(nodes);
free(arcs);
}
template <typename captype, typename tcaptype, typename flowtype> void Graph<captype,tcaptype,flowtype>::reset()
{
node_last = nodes;
arc_last = arcs;
node_num = 0;
if (nodeptr_block) {
delete nodeptr_block;
nodeptr_block = NULL;
}
maxflow_iteration = 0;
flow = 0;
}
template <typename captype, typename tcaptype, typename flowtype> void Graph<captype,tcaptype,flowtype>::reallocate_nodes(int num)
{
int node_num_max = (int)(node_max - nodes);
node *nodes_old = nodes;
node_num_max += node_num_max / 2;
if (node_num_max < node_num + num) {
node_num_max = node_num + num;
}
nodes = (node *)realloc(nodes_old, node_num_max * sizeof(node));
if (!nodes) {
if (error_function) {
(*error_function)("Not enough memory!");
exit(1);
}
}
node_last = nodes + node_num;
node_max = nodes + node_num_max;
if (nodes != nodes_old) {
arc *a;
for (a = arcs; a < arc_last; a++) {
a->head = (node *)((char *)a->head + (((char *)nodes) - ((char *)nodes_old)));
}
}
}
template <typename captype, typename tcaptype, typename flowtype> void Graph<captype, tcaptype, flowtype>::reallocate_arcs()
{
int arc_num_max = (int)(arc_max - arcs);
int arc_num = (int)(arc_last - arcs);
arc *arcs_old = arcs;
arc_num_max += arc_num_max / 2;
if (arc_num_max & 1) {
arc_num_max ++;
}
arcs = (arc *)realloc(arcs_old, arc_num_max * sizeof(arc));
if (!arcs) {
if (error_function) {
(*error_function)("Not enough memory!");
exit(1);
}
}
arc_last = arcs + arc_num;
arc_max = arcs + arc_num_max;
if (arcs != arcs_old) {
node *i;
arc *a;
for (i = nodes; i < node_last; i++) {
if (i->first) i->first = (arc *)((char *)i->first + (((char *) arcs) - ((char *) arcs_old)));
}
for (a = arcs; a < arc_last; a++) {
if (a->next) a->next = (arc *)((char *)a->next + (((char *)arcs) - ((char *)arcs_old)));
a->sister = (arc *)((char *)a->sister + (((char *)arcs) - ((char *)arcs_old)));
}
}
}
コード:
// Histgram.cpp
#include "Histgram.h"
using namespace cv;
Histgram::Histgram()
{
bins = 4;
}
float Histgram::operator()(Vec3f color) const
{
int num = 256 / bins;
return (histgram.at<float>((int)color[0] / num, (int)color[1] / num, (int)color[2] / num)) / sum;
}
void Histgram::CreateHistrgram(const Mat img, Mat mask)
{
float RGBranges[] = {0,
256};
int histSize[] = {bins,
bins,
bins};
const float *ranges[] = {RGBranges,
RGBranges,
RGBranges};
int channels[] = {0,
1,
2};
calcHist(&img, 1, channels, mask, histgram, 3, histSize, ranges, true, false);
sum = 0.0;
float binVal;
for (int b = 0; b < bins; b++) {
for (int g = 0; g < bins; g++) {
for (int r = 0; r < bins; r++) {
binVal = histgram.at<float>(b, g, r);
sum += binVal;
}
}
}
}
コード:
// maxflow.cpp
#include <stdio.h>
#include <iostream>
#include "graph.h"
#include "instances.inc"
using namespace std;
#define TERMINAL ((arc *) 1)
#define ORPHAN ((arc *) 2)
#define INFINITE_D ((int)(((unsigned)-1) / 2))
template <typename captype, typename tcaptype, typename flowtype> inline void Graph<captype, tcaptype, flowtype>::set_active(node *i)
{
if (!i->next) {
if (queue_last[1]) {
queue_last[1]->next = i;
}
else {
queue_first[1] = i;
}
queue_last[1] = i;
i->next = i;
}
}
template <typename captype, typename tcaptype, typename flowtype> inline typename Graph<captype, tcaptype, flowtype>::node *Graph<captype, tcaptype, flowtype>::next_active()
{
node *i;
while (1) {
if (!(i = queue_first[0])) {
queue_first[0] = i = queue_first[1];
queue_last[0] = queue_last[1];
queue_first[1] = NULL;
queue_last[1] = NULL;
if (!i) {
return NULL;
}
}
if (i->next == i) {
queue_first[0] = queue_last[0] = NULL;
}
else {
queue_first[0] = i->next;
}
i->next = NULL;
if (i->parent) {
return i;
}
}
}
template <typename captype, typename tcaptype, typename flowtype> inline void Graph<captype, tcaptype, flowtype>::set_orphan_front(node *i)
{
nodeptr *np;
i->parent = ORPHAN;
np = nodeptr_block->New();
np->ptr = i;
np->next = orphan_first;
orphan_first = np;
}
template <typename captype, typename tcaptype, typename flowtype> inline void Graph<captype, tcaptype, flowtype>::set_orphan_rear(node *i)
{
nodeptr *np;
i->parent = ORPHAN;
np = nodeptr_block->New();
np->ptr = i;
if (orphan_last) {
orphan_last->next = np;
}
else {
orphan_first = np;
}
orphan_last = np;
np->next = NULL;
}
template <typename captype, typename tcaptype, typename flowtype> inline void Graph<captype, tcaptype, flowtype>::add_to_changed_list(node *i)
{
if (changed_list && !i->is_in_changed_list) {
node_id *ptr = changed_list->New();
*ptr = (node_id)(i - nodes);
i->is_in_changed_list = true;
}
}
template <typename captype, typename tcaptype, typename flowtype> void Graph<captype, tcaptype, flowtype>::maxflow_init()
{
node *i;
queue_first[0] = queue_last[0] = NULL;
queue_first[1] = queue_last[1] = NULL;
orphan_first = NULL;
TIME = 0;
for (i = nodes; i<node_last; i++) {
i->next = NULL;
i->is_marked = 0;
i->is_in_changed_list = 0;
i->TS = TIME;
if (i->tr_cap > 0) {
i->is_sink = 0;
i->parent = TERMINAL;
set_active(i);
i->DIST = 1;
}
else if (i->tr_cap < 0) {
i->is_sink = 1;
i->parent = TERMINAL;
set_active(i);
i->DIST = 1;
}
else {
i->parent = NULL;
}
}
}
template <typename captype, typename tcaptype, typename flowtype> void Graph<captype, tcaptype, flowtype>::maxflow_reuse_trees_init()
{
node *i;
node *j;
node *queue = queue_first[1];
arc *a;
nodeptr *np;
queue_first[0] = queue_last[0] = NULL;
queue_first[1] = queue_last[1] = NULL;
orphan_first = orphan_last = NULL;
TIME++;
while ((i = queue)) {
queue = i->next;
if (queue == i) {
queue = NULL;
}
i->next = NULL;
i->is_marked = 0;
set_active(i);
if (i->tr_cap == 0) {
if (i->parent) set_orphan_rear(i);
continue;
}
if (i->tr_cap > 0) {
if (!i->parent || i->is_sink) {
i->is_sink = 0;
for (a = i->first; a; a = a->next) {
j = a->head;
if (!j->is_marked) {
if (j->parent == a->sister) set_orphan_rear(j);
if (j->parent && j->is_sink && a->r_cap > 0) set_active(j);
}
}
add_to_changed_list(i);
}
}
else {
if (!i->parent || !i->is_sink) {
i->is_sink = 1;
for (a = i->first; a; a = a->next) {
j = a->head;
if (!j->is_marked) {
if (j->parent == a->sister) {
set_orphan_rear(j);
}
if (j->parent && !j->is_sink && a->sister->r_cap > 0) {
set_active(j);
}
}
}
add_to_changed_list(i);
}
}
i->parent = TERMINAL;
i->TS = TIME;
i->DIST = 1;
}
while ((np = orphan_first)) {
orphan_first = np->next;
i = np->ptr;
nodeptr_block->Delete(np);
if (!orphan_first) {
orphan_last = NULL;
}
if (i->is_sink) {
process_sink_orphan(i);
}
else {
process_source_orphan(i);
}
}
}
template <typename captype, typename tcaptype, typename flowtype> void Graph<captype, tcaptype, flowtype>::augment(arc *middle_arc)
{
node *i;
arc *a;
tcaptype bottleneck;
bottleneck = middle_arc->r_cap;
for (i = middle_arc->sister->head; ; i = a->head) {
a = i->parent;
if (a == TERMINAL) {
break;
}
if (bottleneck > a->sister->r_cap) {
bottleneck = a->sister->r_cap;
}
}
if (bottleneck > i->tr_cap) {
bottleneck = i->tr_cap;
}
for (i = middle_arc->head; ; i = a->head) {
a = i->parent;
if (a == TERMINAL) {
break;
}
if (bottleneck > a->r_cap) {
bottleneck = a->r_cap;
}
}
if (bottleneck > - i->tr_cap) {
bottleneck = - i->tr_cap;
}
middle_arc->sister->r_cap += bottleneck;
middle_arc->r_cap -= bottleneck;
for (i = middle_arc->sister->head; ; i = a->head) {
a = i->parent;
if (a == TERMINAL) {
break;
}
a->r_cap += bottleneck;
a->sister->r_cap -= bottleneck;
if (!a->sister->r_cap) {
set_orphan_front(i);
}
}
i->tr_cap -= bottleneck;
if (!i->tr_cap) {
set_orphan_front(i);
}
for (i = middle_arc->head; ; i = a->head) {
a = i->parent;
if (a == TERMINAL) {
break;
}
a->sister->r_cap += bottleneck;
a->r_cap -= bottleneck;
if (!a->r_cap) {
set_orphan_front(i);
}
}
i->tr_cap += bottleneck;
if (!i->tr_cap) {
set_orphan_front(i);
}
flow += bottleneck;
}
template <typename captype, typename tcaptype, typename flowtype> void Graph<captype, tcaptype, flowtype>::process_source_orphan(node *i)
{
node *j;
arc *a0, *a0_min = NULL, *a;
int d, d_min = INFINITE_D;
for (a0 = i->first; a0; a0 = a0->next)
if (a0->sister->r_cap) {
j = a0->head;
if (!j->is_sink && (a = j->parent)) {
d = 0;
while (1) {
if (j->TS == TIME) {
d += j->DIST;
break;
}
a = j->parent;
d++;
if (a == TERMINAL) {
j->TS = TIME;
j->DIST = 1;
break;
}
if (a == ORPHAN) {
d = INFINITE_D;
break;
}
j = a->head;
}
if (d<INFINITE_D) {
if (d < d_min) {
a0_min = a0;
d_min = d;
}
for (j = a0->head; j->TS != TIME; j = j->parent->head) {
j->TS = TIME;
j->DIST = d--;
}
}
}
}
if (i->parent = a0_min) {
i->TS = TIME;
i->DIST = d_min + 1;
}
else {
add_to_changed_list(i);
for (a0 = i->first; a0; a0 = a0->next) {
j = a0->head;
if (!j->is_sink && (a = j->parent)) {
if (a0->sister->r_cap) {
set_active(j);
}
if (a != TERMINAL && a!=ORPHAN && a->head == i) {
set_orphan_rear(j);
}
}
}
}
}
template <typename captype, typename tcaptype, typename flowtype> void Graph<captype, tcaptype, flowtype>::process_sink_orphan(node *i)
{
node *j;
arc *a0, *a0_min = NULL, *a;
int d, d_min = INFINITE_D;
for (a0 = i->first; a0; a0 = a0->next)
if (a0->r_cap) {
j = a0->head;
if (j->is_sink && (a = j->parent)) {
d = 0;
while (1) {
if (j->TS == TIME) {
d += j->DIST;
break;
}
a = j->parent;
d++;
if (a == TERMINAL) {
j->TS = TIME;
j->DIST = 1;
break;
}
if (a == ORPHAN) {
d = INFINITE_D;
break;
}
j = a->head;
}
if (d < INFINITE_D) {
if (d < d_min) {
a0_min = a0;
d_min = d;
}
for (j = a0->head; j->TS != TIME; j = j->parent->head) {
j->TS = TIME;
j->DIST = d--;
}
}
}
}
if (i->parent = a0_min) {
i->TS = TIME;
i->DIST = d_min + 1;
}
else {
add_to_changed_list(i);
for (a0 = i->first; a0; a0 = a0->next) {
j = a0->head;
if (j->is_sink && (a = j->parent)) {
if (a0->r_cap) set_active(j);
if (a != TERMINAL && a != ORPHAN && a->head == i) {
set_orphan_rear(j);
}
}
}
}
}
template <typename captype, typename tcaptype, typename flowtype> flowtype Graph<captype, tcaptype, flowtype>::maxflow(bool reuse_trees, Block<node_id> *_changed_list)
{
node *i, *j, *current_node = NULL;
arc *a;
nodeptr *np, *np_next;
if (!nodeptr_block) {
nodeptr_block = new DBlock<nodeptr>(NODEPTR_BLOCK_SIZE, error_function);
}
changed_list = _changed_list;
if (maxflow_iteration == 0 && reuse_trees) {
if (error_function) {
(*error_function)("reuse_trees cannot be used in the first call to maxflow()!");
exit(1);
}
}
if (changed_list && !reuse_trees) {
if (error_function) {
(*error_function)("changed_list cannot be used without reuse_trees!");
exit(1);
}
}
if (reuse_trees) {
maxflow_reuse_trees_init();
}
else {
maxflow_init();
}
while (1) {
if ((i = current_node)) {
i->next = NULL;
if (!i->parent) {
i = NULL;
}
}
if (!i) {
if (!(i = next_active())) {
break;
}
}
if (!i->is_sink) {
for (a = i->first; a; a = a->next) {
if (a->r_cap) {
j = a->head;
if (!j->parent) {
j->is_sink = 0;
j->parent = a->sister;
j->TS = i->TS;
j->DIST = i->DIST + 1;
set_active(j);
add_to_changed_list(j);
}
else if (j->is_sink) {
break;
}
else if (j->TS <= i->TS && j->DIST > i->DIST) {
j->parent = a->sister;
j->TS = i->TS;
j->DIST = i->DIST + 1;
}
}
}
}
else {
for (a = i->first; a; a = a->next)
if (a->sister->r_cap) {
j = a->head;
if (!j->parent) {
j->is_sink = 1;
j->parent = a->sister;
j->TS = i->TS;
j->DIST = i->DIST + 1;
set_active(j);
add_to_changed_list(j);
}
else if (!j->is_sink) {
a = a->sister;
break;
}
else if (j->TS <= i->TS && j->DIST > i->DIST) {
j->parent = a->sister;
j->TS = i->TS;
j->DIST = i->DIST + 1;
}
}
}
TIME++;
if (a) {
i->next = i;
current_node = i;
augment(a);
while ((np = orphan_first)) {
np_next = np->next;
np->next = NULL;
while ((np = orphan_first)) {
orphan_first = np->next;
i = np->ptr;
nodeptr_block->Delete(np);
if (!orphan_first) {
orphan_last = NULL;
}
if (i->is_sink) {
process_sink_orphan(i);
}
else {
process_source_orphan(i);
}
}
orphan_first = np_next;
}
}
else current_node = NULL;
}
if (!reuse_trees || (maxflow_iteration % 64) == 0) {
delete nodeptr_block;
nodeptr_block = NULL;
}
maxflow_iteration++;
return flow;
}
template <typename captype, typename tcaptype, typename flowtype> void Graph<captype, tcaptype, flowtype>::test_consistency(node *current_node)
{
node *i;
arc *a;
int r;
int num1 = 0, num2 = 0;
for (i = nodes; i < node_last; i++) {
if (i->next || i==current_node) {
num1++;
}
}
for (r = 0; r < 3; r++) {
i = (r == 2) ? current_node : queue_first[r];
if (i) {
for ( ; ; i = i->next) {
num2 ++;
if (i->next == i) {
if (r < 2) {
assert(i == queue_last[r]);
}
else {
assert(i == current_node);
break;
}
}
}
}
}
assert(num1 == num2);
for (i = nodes; i < node_last; i++) {
if (i->parent == NULL) {
}
else if (i->parent == ORPHAN) {
}
else if (i->parent == TERMINAL) {
if (!i->is_sink) {
assert(i->tr_cap > 0);
}
else {
assert(i->tr_cap < 0);
}
}
else {
if (!i->is_sink) {
assert (i->parent->sister->r_cap > 0);
}
else {
assert (i->parent->r_cap > 0);
}
}
if (i->parent && !i->next) {
if (!i->is_sink) {
assert(i->tr_cap >= 0);
for (a = i->first; a; a = a->next) {
if (a->r_cap > 0) {
assert(a->head->parent && !a->head->is_sink);
}
}
}
else {
assert(i->tr_cap <= 0);
for (a = i->first; a; a = a->next) {
if (a->sister->r_cap > 0) {
assert(a->head->parent && a->head->is_sink);
}
}
}
}
if (i->parent && i->parent!=ORPHAN && i->parent != TERMINAL) {
assert(i->TS <= i->parent->head->TS);
if (i->TS == i->parent->head->TS) {
assert(i->DIST > i->parent->head->DIST);
}
}
}
}
コード:
// main.cpp
#include "GCApplication.h"
using namespace cv;
using namespace std;
GCApplication gcApp;
void on_mouse1(int event, int x, int y, int flags, void *param)
{
gcApp.MouseClick(event, x, y, flags, param);
}
int main(int argc, char *argv[])
{
Mat img;
if (argc == 1) {
string fileName;
cout << "Image name : ";
cin >> fileName;
if (fileName.empty()) {
return -1;
}
img = imread(fileName);
}
else {
img = imread(argv[1]);
}
if (img.empty()) {
cout << "Not image!" << endl;
return -1;
}
const string winName = "graph cut";
cvNamedWindow(winName.c_str(), 0);
cout << "-------------- How to use --------------" << endl;
cout << "Left mouse button : Foreground seed" << endl;
cout << "Right mouse button : Background seed" << endl;
cout << "s : Run of GraphCut" << endl;
cout << "Esc : Exit\n" << endl;
gcApp.SetImageAndWinName(img, winName);
gcApp.ShowImage();
cvSetMouseCallback(winName.c_str(), on_mouse1, 0);
int c = cvWaitKey(0);
switch ((char)c) {
case 's':
gcApp.GraphCut();
cout << "End of run of GraphCut!\n" << endl;
cout << "Press any key to continue..." << endl;
waitKey();
return 0;
case '\x1b':
cout << "Exiting..." << endl;
cvDestroyWindow(winName.c_str());
return 0;
}
return 0;
}
コード:
$ ls
GCApplication.cpp GCApplication.h GMM.cpp GMM.h Histgram.cpp Histgram.h block.h graph.cpp graph.h instances.inc main.cpp maxflow.cpp
$ g++ -c GCApplication.cpp
GCApplication.cpp: In member function ‘void GCApplication::Reset()’:
GCApplication.cpp:75: error: ambiguous overload for ‘operator=’ in ‘((GCApplication*)this)->GCApplication::bgdModel = 0’
/usr/local/include/opencv2/core/mat.hpp:281: note: candidates are: cv::Mat& cv::Mat::operator=(const cv::Mat&)
/usr/local/include/opencv2/core/core.hpp:1730: note: cv::Mat& cv::Mat::operator=(const cv::Scalar&)
GCApplication.cpp: In member function ‘void GCApplication::InitGMMs(const cv::Mat&, const cv::Mat&, GMM&, GMM&)’:
GCApplication.cpp:385: error: invalid initialization of reference of type ‘const cv::_OutputArray&’ from expression of type ‘int’
/usr/local/include/opencv2/core/core.hpp:2478: error: in passing argument 7 of ‘double cv::kmeans(const cv::_InputArray&, int, const cv::_OutputArray&, cv::TermCriteria, int, int, const cv::_OutputArray&)’
GCApplication.cpp:388: error: invalid initialization of reference of type ‘const cv::_OutputArray&’ from expression of type ‘int’
/usr/local/include/opencv2/core/core.hpp:2478: error: in passing argument 7 of ‘double cv::kmeans(const cv::_InputArray&, int, const cv::_OutputArray&, cv::TermCriteria, int, int, const cv::_OutputArray&)’
$ g++ -c GMM.cpp
$ g++ -c Histgram.cpp
$ g++ -c graph.cpp
graph.cpp: In constructor ‘Graph<captype, tcaptype, flowtype>::Graph(int, int, void (*)(char*)) [with captype = int, tcaptype = int, flowtype = int]’:
instances.inc:7: instantiated from here
graph.cpp:31: 警告: deprecated conversion from string constant to ‘char*’
graph.cpp: In member function ‘void Graph<captype, tcaptype, flowtype>::reallocate_nodes(int) [with captype = int, tcaptype = int, flowtype = int]’:
instances.inc:7: instantiated from here
graph.cpp:87: 警告: deprecated conversion from string constant to ‘char*’
graph.cpp: In member function ‘void Graph<captype, tcaptype, flowtype>::reallocate_arcs() [with captype = int, tcaptype = int, flowtype = int]’:
instances.inc:7: instantiated from here
graph.cpp:121: 警告: deprecated conversion from string constant to ‘char*’
graph.cpp: In constructor ‘Graph<captype, tcaptype, flowtype>::Graph(int, int, void (*)(char*)) [with captype = short int, tcaptype = int, flowtype = int]’:
instances.inc:8: instantiated from here
graph.cpp:31: 警告: deprecated conversion from string constant to ‘char*’
graph.cpp: In member function ‘void Graph<captype, tcaptype, flowtype>::reallocate_nodes(int) [with captype = short int, tcaptype = int, flowtype = int]’:
instances.inc:8: instantiated from here
graph.cpp:87: 警告: deprecated conversion from string constant to ‘char*’
graph.cpp: In member function ‘void Graph<captype, tcaptype, flowtype>::reallocate_arcs() [with captype = short int, tcaptype = int, flowtype = int]’:
instances.inc:8: instantiated from here
graph.cpp:121: 警告: deprecated conversion from string constant to ‘char*’
graph.cpp: In constructor ‘Graph<captype, tcaptype, flowtype>::Graph(int, int, void (*)(char*)) [with captype = float, tcaptype = float, flowtype = float]’:
instances.inc:9: instantiated from here
graph.cpp:31: 警告: deprecated conversion from string constant to ‘char*’
graph.cpp: In member function ‘void Graph<captype, tcaptype, flowtype>::reallocate_nodes(int) [with captype = float, tcaptype = float, flowtype = float]’:
instances.inc:9: instantiated from here
graph.cpp:87: 警告: deprecated conversion from string constant to ‘char*’
graph.cpp: In member function ‘void Graph<captype, tcaptype, flowtype>::reallocate_arcs() [with captype = float, tcaptype = float, flowtype = float]’:
instances.inc:9: instantiated from here
graph.cpp:121: 警告: deprecated conversion from string constant to ‘char*’
graph.cpp: In constructor ‘Graph<captype, tcaptype, flowtype>::Graph(int, int, void (*)(char*)) [with captype = double, tcaptype = double, flowtype = double]’:
instances.inc:10: instantiated from here
graph.cpp:31: 警告: deprecated conversion from string constant to ‘char*’
graph.cpp: In member function ‘void Graph<captype, tcaptype, flowtype>::reallocate_nodes(int) [with captype = double, tcaptype = double, flowtype = double]’:
instances.inc:10: instantiated from here
graph.cpp:87: 警告: deprecated conversion from string constant to ‘char*’
graph.cpp: In member function ‘void Graph<captype, tcaptype, flowtype>::reallocate_arcs() [with captype = double, tcaptype = double, flowtype = double]’:
instances.inc:10: instantiated from here
graph.cpp:121: 警告: deprecated conversion from string constant to ‘char*’
$ g++ -c main.cpp
$ g++ -c maxflow.cpp
maxflow.cpp: In member function ‘flowtype Graph<captype, tcaptype, flowtype>::maxflow(bool, Block<int>*) [with captype = int, tcaptype = int, flowtype = int]’:
instances.inc:7: instantiated from here
maxflow.cpp:457: 警告: deprecated conversion from string constant to ‘char*’
maxflow.cpp:464: 警告: deprecated conversion from string constant to ‘char*’
maxflow.cpp: In member function ‘flowtype Graph<captype, tcaptype, flowtype>::maxflow(bool, Block<int>*) [with captype = short int, tcaptype = int, flowtype = int]’:
instances.inc:8: instantiated from here
maxflow.cpp:457: 警告: deprecated conversion from string constant to ‘char*’
maxflow.cpp:464: 警告: deprecated conversion from string constant to ‘char*’
maxflow.cpp: In member function ‘flowtype Graph<captype, tcaptype, flowtype>::maxflow(bool, Block<int>*) [with captype = float, tcaptype = float, flowtype = float]’:
instances.inc:9: instantiated from here
maxflow.cpp:457: 警告: deprecated conversion from string constant to ‘char*’
maxflow.cpp:464: 警告: deprecated conversion from string constant to ‘char*’
maxflow.cpp: In member function ‘flowtype Graph<captype, tcaptype, flowtype>::maxflow(bool, Block<int>*) [with captype = double, tcaptype = double, flowtype = double]’:
instances.inc:10: instantiated from here
maxflow.cpp:457: 警告: deprecated conversion from string constant to ‘char*’
maxflow.cpp:464: 警告: deprecated conversion from string constant to ‘char*’
In file included from graph.h:6,
from maxflow.cpp:3:
block.h: In member function ‘Type* DBlock<Type>::New() [with Type = Graph<int, int, int>::nodeptr]’:
maxflow.cpp:59: instantiated from ‘void Graph<captype, tcaptype, flowtype>::set_orphan_front(Graph<captype, tcaptype, flowtype>::node*) [with captype = int, tcaptype = int, flowtype = int]’
instances.inc:7: instantiated from here
block.h:146: 警告: deprecated conversion from string constant to ‘char*’
block.h: In member function ‘Type* Block<Type>::New(int) [with Type = int]’:
maxflow.cpp:85: instantiated from ‘void Graph<captype, tcaptype, flowtype>::add_to_changed_list(Graph<captype, tcaptype, flowtype>::node*) [with captype = int, tcaptype = int, flowtype = int]’
instances.inc:7: instantiated from here
block.h:35: 警告: deprecated conversion from string constant to ‘char*’
block.h: In member function ‘Type* DBlock<Type>::New() [with Type = Graph<short int, int, int>::nodeptr]’:
maxflow.cpp:59: instantiated from ‘void Graph<captype, tcaptype, flowtype>::set_orphan_front(Graph<captype, tcaptype, flowtype>::node*) [with captype = short int, tcaptype = int, flowtype = int]’
instances.inc:8: instantiated from here
block.h:146: 警告: deprecated conversion from string constant to ‘char*’
block.h: In member function ‘Type* DBlock<Type>::New() [with Type = Graph<float, float, float>::nodeptr]’:
maxflow.cpp:59: instantiated from ‘void Graph<captype, tcaptype, flowtype>::set_orphan_front(Graph<captype, tcaptype, flowtype>::node*) [with captype = float, tcaptype = float, flowtype = float]’
instances.inc:9: instantiated from here
block.h:146: 警告: deprecated conversion from string constant to ‘char*’
block.h: In member function ‘Type* DBlock<Type>::New() [with Type = Graph<double, double, double>::nodeptr]’:
maxflow.cpp:59: instantiated from ‘void Graph<captype, tcaptype, flowtype>::set_orphan_front(Graph<captype, tcaptype, flowtype>::node*) [with captype = double, tcaptype = double, flowtype = double]’
instances.inc:10: instantiated from here
block.h:146: 警告: deprecated conversion from string constant to ‘char*’
main.cppとGCApplication.cppは個人的に必要のない機能を削除したり、他のコードはwindows.hを消したりしました。
GMM.cppやHistgram.cpp、main.cpp以外はコンパイルすると上記のようなエラーや警告が出ているのですが、エラーや警告の意味がわからないのと、どう書き直せばいいのかがわかりません・・・