Question

J'écris un programme qui préformera la synthèse de texture. Je suis loin du C ++ depuis un moment et j'ai du mal à comprendre ce que je fais de mal dans ma classe. Lorsque j'exécute le programme, j'obtiens une exception non gérée dans la fonction copyToSample lorsqu'il tente d'accéder aux tableaux. Il est appelé à partir de la fonction bestSampleSearch lorsque l'exception non gérée se produit. La fonction a été appelée auparavant et fonctionne très bien, mais plus tard dans le programme, elle est appelée une deuxième fois et échoue. Des idées? Faites-moi savoir si quelqu'un a besoin de plus de code. Merci!

Edit1: Ajout de la fonction bestSampleSearch et de la fonction compareMetaPic
Edit2: Ajout d'un constructeur de copie
Edit3: Ajout de main ()
Edit4: J'ai fait fonctionner le programme. Cependant, il y a maintenant une fuite de mémoire ou je manque de mémoire lorsque j'exécute le programme. Il semble que dans la double boucle for de main qui commence "// tandis que l'image de sortie est vide" est le problème. Si je commente cette partie, le programme se termine en temps opportun mais un seul petit carré est sorti. Quelque chose ne va pas avec ma fonction bestSampleSearch.

MetaPic.h

#pragma once
#include <pic.h>
#include <stdlib.h>
#include <cmath>

class MetaPic
{
    public:
        Pic* source;
        Pixel1*** meta;
        int x;
        int y;
        int z;
        MetaPic();
        MetaPic(Pic*);
        MetaPic(const MetaPic&);
        MetaPic& operator=(const MetaPic&);
        ~MetaPic();
        void allocateMetaPic();
        void copyPixelData();
        void copyToOutput(Pic*&);
        void copyToMetaOutput(MetaPic&, int, int);
        void copyToSample(MetaPic&, int, int);
        void freeMetaPic();

};

MetaPic.cpp

#include "MetaPic.h"

MetaPic::MetaPic()
{
    source = NULL;
    meta = NULL;
    x = 0;
    y = 0;
    z = 0;
}

MetaPic::MetaPic(Pic* pic)
{
    source = pic;
    x = pic->nx;
    y = pic->ny;
    z = pic->bpp;
    allocateMetaPic();
    copyPixelData();
}

MetaPic::MetaPic(const MetaPic& mp)
{
    source = mp.source;
    x = mp.x;
    y = mp.y;
    z = mp.z;
    allocateMetaPic();
    copyPixelData();
}

MetaPic::~MetaPic()
{
    freeMetaPic();
}

// create a 3 dimensional array from the original one dimensional array
void MetaPic::allocateMetaPic()
{
    meta = (Pixel1***)calloc(x, sizeof(Pixel1**));

    for(int i = 0; i < x; i++)
    {
        meta[i] = (Pixel1**)calloc(y, sizeof(Pixel1*));
        for(int j = 0; j < y; j++)
        {
            meta[i][j] = (Pixel1*)calloc(z, sizeof(Pixel1));
        }
    }
}

void MetaPic::copyPixelData()
{
    for(int j = 0; j < y; j++)
    {
        for(int i = 0; i < x; i++)
        {
            for(int k = 0; k < z; k++)
                meta[i][j][k] = source->pix[(j*z*x)+(i*z)+k];
        }
    }
}

void MetaPic::copyToOutput(Pic* &output)
{
    for(int j = 0; j < y; j++)
    {
        for(int i = 0; i < x; i++)
        {
            for(int k = 0; k < z; k++)
                output->pix[(j*z*x)+(i*z)+k] = meta[i][j][k];
        }
    }
}

// copy the meta data to the final  pic output starting at the top left of the picture     and mapped to 'a' and 'b' coordinates in the output
void MetaPic::copyToMetaOutput(MetaPic &output, int a, int b)
{
    for(int j = 0; (j < y) && ((j+b) < output.y); j++)
    {
        for(int i = 0; (i < x) && ((i+a) < output.x); i++)
        {
            for(int k = 0; k < z; k++)
                output.meta[i+a][j+b][k] = meta[i][j][k];
        }
    }
}

// copies from a source image to a smaller sample image
// *** Must make sure that the x and y coordinates have enough buffer space ***
void MetaPic::copyToSample(MetaPic &sample, int a, int b)
{
    for(int j = 0; (j < sample.y) && ((b+j) < y); j++)
    {
        for(int i = 0; i < (sample.x) && ((a+i) < x); i++)
        {
            for(int k = 0; k < sample.z; k++)
            {
                    **sample.meta[i][j][k] = meta[i+a][j+b][k];**
            }
        }
    }
}

// free the meta pic data (MetaPic.meta)
// *** Not to be used outside of class declaration ***
void MetaPic::freeMetaPic()
{
    for(int j = 0; j < y; j++)
    {
        for(int i = 0; i < z; i++)
            free(meta[i][j]);
    }
    for(int i = 0; i < x; i++)
        free(meta[i]);

    free(meta);
}

MetaPic MetaPic::operator=(MetaPic mp)
{
    MetaPic newMP(mp.source);

    return newMP;
}

main.cpp

#ifdef WIN32
// For VC++ you need to include this file as glut.h and gl.h refer to it
#include <windows.h>
// disable the warning for the use of strdup and friends
#pragma warning(disable:4996) 
#endif
#include <stdio.h>     // Standard Header For Most Programs
#include <stdlib.h>    // Additional standard Functions (exit() for example)
#include <iostream>
// Interface to libpicio, provides functions to load/save jpeg files
#include <pic.h>
#include <string.h>
#include <time.h>
#include <cmath>

#include "MetaPic.h"

using namespace std;

MetaPic bestSampleSearch(MetaPic, MetaPic);
double compareMetaPics(MetaPic, MetaPic);

#define SAMPLE_SIZE 23
#define OVERLAP 9

// Texture source image (pic.h uses the Pic* data structure)
Pic *sourceImage;
Pic *outputImage;
int main(int argc, char* argv[])
{
    char* pictureName = "reg1.jpg";
    int outputWidth = 0;
    int outputHeight = 0;

    // attempt to read in the file name
    sourceImage = pic_read(pictureName, NULL);
    if(sourceImage == NULL)
    {
        cout << "Couldn't read the file" << endl;
        system("pause");
        exit(EXIT_FAILURE);
    }

    // *** For now set the output image to 3 times the original height and width ***
    outputWidth = sourceImage->nx*3;
    outputHeight = sourceImage->ny*3;

    // allocate the output image
    outputImage = pic_alloc(outputWidth, outputHeight, sourceImage->bpp, NULL);
    Pic* currentImage = pic_alloc(SAMPLE_SIZE, SAMPLE_SIZE, sourceImage->bpp, NULL);

    MetaPic metaSource(sourceImage);
    MetaPic metaOutput(outputImage);
    MetaPic metaCurrent(currentImage);

    // seed the output image    
    int x = 0;
    int y = 0;
    int xupperbound = metaSource.x - SAMPLE_SIZE;
    int yupperbound = metaSource.y - SAMPLE_SIZE;
    int xlowerbound = 0;
    int ylowerbound = 0;

    // find random coordinates
    srand(time(NULL));
    while((x >= xupperbound) || (x <= xlowerbound))
        x = rand() % metaSource.x;
    while((y >= yupperbound) || (y <= ylowerbound))
        y = rand() % metaSource.y;

    // copy a random sample from the source to the metasample
    metaSource.copyToSample(metaCurrent, x, y);
    // copy the seed to the metaoutput
    metaCurrent.copyToMetaOutput(metaOutput, 0, 0);


    int currentOutputX = 0;
    int currentOutputY = 0;

    // while the output picture is unfilled...
    for(int j = 0; j < yupperbound; j+=(SAMPLE_SIZE-OVERLAP))
    {
        for(int i = 0; i < xupperbound; i+=(SAMPLE_SIZE-OVERLAP))
        {
            // move the sample to correct overlap
            metaSource.copyToSample(metaCurrent, i, j);
            // find the best match for the sample
            metaCurrent = bestSampleSearch(metaSource, metaCurrent);
            // write the best match to the metaoutput
            metaCurrent.copyToMetaOutput(metaOutput, i, j);
            // update the values
        }
    }


    // copy the metaOutput to the output
    metaOutput.copyToOutput(outputImage);

    // output the image
    pic_write("reg1_output.jpg", outputImage, PIC_JPEG_FILE);


    // clean up
    pic_free(sourceImage);
    pic_free(outputImage);
    pic_free(currentImage);

    // return success
    cout << "Done!" << endl;
    system("pause");
    // return success
    return 0;
}

// finds the best sample to insert into the image
// *** best must be the sample which consists of the overlap ***
MetaPic bestSampleSearch(MetaPic source, MetaPic best)
{
    MetaPic metaSample(best);

    double bestScore = 999999.0;
    double currentScore = 0.0;

    for(int j = 0; j < source.y; j++)
    {
        for(int i = 0; i < source.x; i++)
        {
            // copy the image starting at the top left of the source image
            source.copyToSample(metaSample, i, j);
            // compare the sample with the overlap
            currentScore = compareMetaPics(best, metaSample);
            // if best score is greater than current score then copy the         better sample to best and continue searching
            if( bestScore > currentScore)
            {
                metaSample.copyToSample(best, 0, 0);
                bestScore = currentScore;
            }
            // otherwise, the score is less than current score then do nothing     (a better sample has not been found)

        }
    }

    return best;
}

// find the comparison score for the two MetaPics based on their rgb values
// *** Both of the meta pics should be the same size ***
double compareMetaPics(MetaPic pic1, MetaPic pic2)
{
    float r1 = 0.0;
    float g1 = 0.0;
    float b1 = 0.0;
    float r2 = 0.0;
    float g2 = 0.0;
    float b2 = 0.0;
    float r = 0.0;
    float g = 0.0;
    float b = 0.0;

    float sum = 0.0;

    // take the sum of the (sqrt((r1-r2)^2 + ((g1-g2)^2 + ((b1-b2)^2))
    for(int j = 0; (j < pic1.y) && (j < pic2.y); j++)
    {
        for(int i = 0; (i < pic1.x) && (i < pic2.x); i++)
        {
            r1 = PIC_PIXEL(pic1.source, i, j, 0);
            r2 = PIC_PIXEL(pic2.source, i, j, 0);
            g1 = PIC_PIXEL(pic1.source, i, j, 1);
            g2 = PIC_PIXEL(pic2.source, i, j, 1);
            b1 = PIC_PIXEL(pic1.source, i, j, 2);
            b2 = PIC_PIXEL(pic2.source, i, j, 2);

            r = r1 - r2;
            g = g1 - g2;
            b = b1 - b2;

            sum += sqrt((r*r) + (g*g) + (b*b));
        }
    }

    return sum;
}
Était-ce utile?

La solution 2

Il s'avère que la fonction de désallocation est incorrecte.Il devrait libérer de la même manière qu'il allouait.

void MetaPic::freeMetaPic()

{

    for(int j = 0; j < y; j++)

    {

        for(int i = 0; i < z; i++)

            free(meta[i][j]);

    }

    for(int i = 0; i < x; i++)

        free(meta[i]);



    free(meta);

}

Autres conseils

Je ne suis pas sûr que ce soit la cause première du problème, mais votre opérateur d'affectation n'attribue en fait rien:

MetaPic MetaPic::operator=(MetaPic mp)
{
    MetaPic newMP(mp.source);

    return newMP;
}

Cela devrait probablement ressembler à ce qui suit (basé sur le code de votre constructeur de copie):

< edit: avec crédit à Alf P. Steinbach

MetaPic& MetaPic::operator=(MetaPic mp)
{
    mp.swap(*this);
    return *this;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top