I tried to implement the labeling algorithm . I adaped an ancien version using IplImage to Map but I am still in trouble .Any idea is welcomed . Thank you very much
const char * const IMAGE_INITIALE = "Initial";
const char * const IMAGE_FINALE = "Final colored image";
using namespace cv;
using namespace std;
Mat initial_image;
int** table_equivalence = new int*;
class RelatePixel {
public:
RelatePixel(int value, RelatePixel * upneighbour, RelatePixel * leftneighbour);
//Mapping
static RelatePixel*** imageToRelatePixelArray(Mat image);
static Mat RelatePixelArrayToImage(RelatePixel** pixels, int nbRows, int nbCol);
//Getters/Setters
void SetLabel(int label);
int GetLabel() const;
RelatePixel* GetVGauche() const;
RelatePixel* GetVHaut() const;
char GetValeur() const;
void SetValeur(char value);
//Utils
bool isNotNull();
ostream& operator<<(ostream &flux);
private:
char value;
int label;
RelatePixel * vUp;
RelatePixel * vLeft;
};
RelatePixel::RelatePixel(int color, RelatePixel * upneighbour, RelatePixel * leftneighbour){
this->value = color;
this->vUp = upneighbour;
this->vLeft = leftneighbour;
this->label = -1;
}
char RelatePixel::GetValeur() const {
return value;
}
void RelatePixel::SetValeur(char value) {
this->value = value;
}
RelatePixel* RelatePixel::GetVGauche() const {
return vLeft;
}
RelatePixel* RelatePixel::GetVHaut() const {
return vUp;
}
void RelatePixel::SetLabel(int label) {
this->label = label;
this->value = 0;//TODO delete
}
int RelatePixel::GetLabel() const {
return label;
}
/**
* Convertit une image en un tableau de RelatePixel
* @param image l'image à modifier
* @return le tableau de RelatePixel correspondant à l'image
*/
RelatePixel*** RelatePixel::imageToRelatePixelArray(Mat image){
cout<<"imageToRelatePixelArray begins"<<endl;
int nbCol = image.cols;
int nbLigne = image.rows;
RelatePixel*** pixels = new RelatePixel**[nbLigne];
int i,j;
RelatePixel * up,* left;
for (i=0; i<nbLigne; i++){
pixels[i] = new RelatePixel*[nbCol];
for (j=0; j<nbCol; j++){
//first line (not neighbour up)
if (i == 0) {
up = NULL;
} else {
up = pixels[i-1][j];
}
//first column (not neighbour left)
if (j == 0) {
left = NULL;
} else {
left = pixels[i][j-1];
}
//Créate pixel
pixels[i][j] = new RelatePixel(image.at<uchar>(Point(i,j))[0], up, left);
}
}
cout<<"imageToRelatePixelArray ends"<<endl;
return pixels;
}
Mat RelatePixel::RelatePixelArrayToImage(RelatePixel** pixels, int nbRows, int nbCol){
Mat img = cvCreateImage(cvSize(nbRows,nbCol),CV_8UC3,1);
cout<<"RelatePixelArrayToImage begins"<<endl;
int i,j,offset;
for (i=0; i<nbRows ; i++){
offset = i*nbCol;
for(j=0; j<nbCol; j++){
img->imageData[j+offset] = pixels[i][j].GetValeur();
}
}
cout<<"RelatePixelArrayToImage ends"<<endl;
return img;
}
bool RelatePixel::isNotNull(){
if (this == NULL) return false;
else return true;
}
ostream& RelatePixel::operator <<(ostream& flux){
flux<<"Pixel : {value: "<<this->GetValeur()
<<", e: "<<this->GetLabel()
<<", vUp: "<<this->GetVHaut()
<<", vGau: "<<this->GetVGauche();
return flux;
}
bool isValidCommand(int nbArgs, char** args);
inline Mat getLabeling();
RelatePixel*** algoLabeling(RelatePixel*** pixels);
int main(int argc, char** argv) {
//verification des arguments du proramme
if (!isValidCommand(argc, argv)) return EXIT_FAILURE;
//initialisation des fenetres
cvNamedWindow(IMAGE_INITIALE);
cvNamedWindow(IMAGE_FINALE);
//Affichage des images
imshow(IMAGE_INITIALE, initial_image);
imshow(IMAGE_FINALE, getLabeling());
//Attente d'une entrée clavier
cvWaitKey();
//fermeture du programme
cvDestroyAllWindows();
return EXIT_SUCCESS;
}
/**
* Verifie la validité des arguments
* @param nbArgs le nombre d'arguments passés
* @param args les arguments
* @return true si les arguments sont valides, false sinon;
*/
bool isValidCommand(int nbArgs, char** args) {
//Verification du nombre d'arguments
if (nbArgs != 2) {
cerr << "Utilisation: \n\t etiquetage <nom_fichier_image>" << endl;
return false;
}
//Chargement des images
Mat tmp = imread(args[1], CV_LOAD_IMAGE_GRAYSCALE);
if (tmp == 0) {
cerr << "Impossible de lire : " << args[1] << "\n";
return false;
}
initial_image = clone(tmp);
return true;
}
RelatePixel*** algoLabeling(RelatePixel*** pixels) {
cout<<"algoLabeling begins"<<endl;
int nbLigne = initial_image.rows;
int nbCol = initial_image.cols;
RelatePixel* pixel, * vup, * vleft;
int currentEtiq = 0, eh, eg;
int i, j;
//loop table RelatePixels
for (i = 0; i < nbLigne; i++) {
for (j = 0; j < nbCol; j++) {
pixel = pixels[i][j];
//if pixel
if (pixel->GetValeur() > 250) {
} else {
//get neighbours up and left
vup = pixel->GetVHaut();
vleft = pixel->GetVGauche();
//if pixel has 2 neighbours
if (vup->isNotNull() && vleft->isNotNull()) {
eh = vup->GetLabel();
eg = vleft->GetLabel();
//if the two neighbours have the same label
if (eh == eg) {
if (eh == -1) { // labels nulles
pixel->SetLabel(currentEtiq++);
} else {
pixel->SetLabel(eh);
}
}
//if the two neighbours have different label
else {
// neighbour up has no label
if (eh == -1) {
pixel->SetLabel(eg);
}
// neighbour left has no label
else if (eg == -1) {
pixel->SetLabel(eh);
}
// labels différentes
else {
pixel->SetLabel(min(eh,eg));
//TODO equiv
}
}
}//if pixel has a least a neighbour null
else {
// 2 neighbours are null
if (!vup->isNotNull() && !vleft->isNotNull()) {
pixel->SetLabel(currentEtiq++);
}// one of two is null
else {
RelatePixel* neighbour;
if (vup->isNotNull()) {
neighbour = vup;
} else {
neighbour = vleft;
}
//verify label neighbour
eh = neighbour->GetLabel();
if (eh >= 0){
pixel->SetLabel(eh);
} else {
pixel->SetLabel(currentEtiq++);
}
}
}
}
}
}
cout<<"algoLabeling ends, currentEtiq = "<<currentEtiq<<endl;
return pixels;
}
Mat getLabeling() {
cout << "getEtiq begins" << endl;
RelatePixel*** pixels = RelatePixel::imageToRelatePixelArray(initial_image);
pixels = algoLabeling(pixels);
//IplImage * img = RelatePixel::RelatePixelArrayToImage(pixels, initial_image->height, initial_image->width);
Mat img = NULL;
cout << "getEtiq ends" << endl;
return img;
}
I have an error with :
- pixels[i][j] = new RelatePixel(image.at(Point(i,j))[0], up, left); - tp1.cpp:116:73: error: invalid types ‘unsigned char[int]’ for array subscript
tp1.cpp:124:28: error: conversion from ‘IplImage* {aka _IplImage*}’ to non-scalar type ‘cv::Mat’ requested Mat img = cvCreateImage(cvSize(nbRows,nbCol),CV_8UC3,1);
img->imageData[j+offset] = pixels[i][j].GetValeur(); tp1.cpp:130:16: error: base operand of ‘->’ has non-pointer type ‘cv::Mat’
- initial_image = clone(tmp); tp1.cpp:193:30: error: cannot convert ‘cv::Mat’ to ‘int ()(void)’ for argument ‘1’ to ‘int clone(int ()(void), void*, int, void*, ...)’
- Mat img = NULL; tp1.cpp:289:15: error: conversion from ‘long int’ to non-scalar type ‘cv::Mat’ requested
image.at<uchar>(Point(i,j))[0]is incorrect.atwill return auchar. So you should not dereference with[0],image.at<uchar>(Point(i,j))should suffice.cvCreateImage is the old API. Just use the
cv::Matconstructor:cv::Mat img(nbRows, nbCol, CV_8UC3);You can get the pointer to the image data by calling
img.ptrI don't see where you've defined this
clone()function, but you aren't passing it the correct parameters. The first parameter expects a function taking no arguments and returning an int.You can't assign
NULLto acv::Matobject. That doesn't make sense.