1
votes

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 :

  1. 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
  2. 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);

  3. img->imageData[j+offset] = pixels[i][j].GetValeur(); tp1.cpp:130:16: error: base operand of ‘->’ has non-pointer type ‘cv::Mat’

  4. 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*, ...)’
  5. Mat img = NULL; tp1.cpp:289:15: error: conversion from ‘long int’ to non-scalar type ‘cv::Mat’ requested
1
could findContours be an alternative?Micka
Yes it would be for sure ^^^ but I have to code the method ;)ana maria

1 Answers

1
votes

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

image.at<uchar>(Point(i,j))[0] is incorrect. at will return a uchar. So you should not dereference with [0], image.at<uchar>(Point(i,j)) should suffice.

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);

cvCreateImage is the old API. Just use the cv::Mat constructor:

cv::Mat img(nbRows, nbCol, CV_8UC3);

img->imageData[j+offset] = pixels[i][j].GetValeur(); tp1.cpp:130:16: error: base operand of ‘->’ has non-pointer type ‘cv::Mat’

You can get the pointer to the image data by calling img.ptr

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*, ...)’

I 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.

Mat img = NULL; tp1.cpp:289:15: error: conversion from ‘long int’ to non-scalar type ‘cv::Mat’ requested

You can't assign NULL to a cv::Mat object. That doesn't make sense.