连接的组件标记算法C

Connected components labeling algorithm C++

本文关键字:算法 组件 连接      更新时间:2023-10-16

我尝试实现标签算法。我使用iPlimage映射了一个Ancien版本,但我仍然遇到麻烦。任何想法都受到欢迎。非常感谢

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: nt 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;
}

我有一个错误:

  1. pixels [i] [j] = new RelatePixel(image.at(point(i,j(([0],向上,左(;-tp1.cpp:116:73:错误:无效类型的"无符号char [int]'for Array下标
  2. tp1.cpp:124:28:错误:从'iplimage* {aka _iplimage*}'转换为非降低类型'cv :: mat'请求垫子img = cvcreateimage(cvsize(cvsize((cvsize(nbrows,nbcol(,CV_8UC3,1(;

  3. img-> imagedata [j offset] =像素[i] [j] .getValeur((;TP1.CPP:130:16:错误:" ->"的基本操作数具有非销钉类型的" CV :: MAT"

  4. initial_image = clone(tmp(;tp1.cpp:193:30:错误:无法将'cv :: mat'转换为'int(((void ('for参数'1'to'int clone(int(int(int(((((void (,void*,int,void*,...('
  5. mat img = null;tp1.cpp:289:15:错误:从"长int"转换为非量表类型'cv :: mat'请求

pixels [i] [j] = new RelatePixel(image.at(point(i,j(([0],向上,左(; - TP1.CPP:116:73:错误:无效类型的"无符号char [int]"数组

image.at<uchar>(Point(i,j))[0]不正确。at将返回uchar。因此,您不应该使用[0]image.at<uchar>(Point(i,j))就足够了。

下标tp1.cpp:124:28:错误:从'iplimage* {aka转换 _iplimage*}’to非量表类型的" cv :: mat"请求垫img = cvcreateimage(cvsize(nbrows,nbcol(,cv_8uc3,1(;

cvcreateimage是旧的API。只需使用cv::Mat构造函数:

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

img-> imagedata [j offset] = pixels [i] [j] .getValeur((;TP1.CPP:130:16: 错误:" ->"的基本操作数具有非销钉类型的" cv :: mat’

您可以通过调用img.ptr

来获取图像数据的指针

initial_image = clone(tmp(;TP1.CPP:193:30:错误:无法转换 " cv :: mat'to" int(((void(" for参数'1'to'int clone(int( (((void(,void*,int,void*,...(’

我看不到您在哪里定义了此clone()函数,但是您并没有将其传递给正确的参数。第一个参数期望一个函数没有参数并返回int。

mat img = null;TP1.CPP:289:15: 错误:从"长int"转换为非量表类型的" cv :: mat" 请求

您无法将NULL分配给cv::Mat对象。这是没有意义的。