Filtracja widma obrazu

0

Witam!
Pracuje aktualnie nad algorytmem który ma za zadanie "wykryć" na obrazie wejściowym rejestrację samochodową (temat pracy licencjackiej) . Po przeprowadzeniu szybkiej transformaty fouriera i otrzymaniu widma obrazu chcę na tym widmie zastosować filtr górnoprzepustowy lub dolnoprzepustowy i wykonać odwrotną transformate fouriera aby zobaczyć jak będzie wyglądał obraz po zastosowaniu filtrów.

Korzystam przy tym z biblioteki OpenCV, fftw3, Qt 4.7.

A o to co mam:

////////////////////////////////////////////////////////////////////////*/ converter.h *//////////////////

 

#ifndef CONVERTER_H
#define CONVERTER_H

#include <iostream>
#include <fftw3.h>
#include <cv.h>
#include <highgui.h>


#include <QImage>
#include <QPixmap>
#include <QPicture>
#include <QRgb>

using namespace cv;


class Converter{
public:
    Converter();
    ~Converter();

    QImage makeN2Dimension(const QImage qImage);
    void transform(char* fileName);

private:
    IplImage *img1;
    IplImage *img2;

    uchar *img1_data;
    uchar *img2_data;

    fftw_complex *data_in;
    fftw_complex *fft;
    fftw_complex *ifft;

    fftw_plan plan_f;
    fftw_plan plan_b;

    int width, height, step;

};

#endif // CONVERTER_H

////////////////////////////////////////////////////////////////////////*/ converter.cpp *//////////////

 

#include <converter.h>

// Konstructor
Converter::Converter(){
    img1 = 0;
    img2 = 0;
    data_in = 0;
    fft = 0;
    ifft = 0;
    plan_f = 0;
    plan_b = 0;
}

// Destructor
Converter::~Converter(){

    // Zwolnij pamięć
    if(img1 != 0)
        cvReleaseImage(&img1);

    if(img2 != 0)
        cvReleaseImage(&img2);

    if(plan_f != 0)
        fftw_destroy_plan(plan_f);

    if(plan_b != 0)
        fftw_destroy_plan(plan_b);

    if(data_in != 0)
        fftw_free( data_in );

    if(fft != 0)
        fftw_free( fft );

    if(ifft != 0)
        fftw_free( ifft );
}

// Dopełnia obraz tak aby boki były tej samej długości
QImage Converter::makeN2Dimension(const QImage qImage){

    QImage n2Image;

    int h = qImage.height();
    int w = qImage.width();

    if(w == h) return qImage;

    if(w == 0 || h == 0) return QImage(100, 100, QImage::Format_RGB888);

    w > h ? n2Image = QImage(w, w, QImage::Format_RGB888) :
            n2Image = QImage(h, h, QImage::Format_RGB888);

        for(int i = 0; i < w; i++)
            for(int j = 0; j < h; j++)
             n2Image.setPixel(i,j, qImage.pixel(i,j));

    return n2Image;
}

void Converter::transform(char* fileName){

    // Wczytaj orginalny obraz
    img1 = cvLoadImage(fileName, CV_LOAD_IMAGE_GRAYSCALE);

    // Sprawdź plik
    if(fileName == 0){
        std::cout<<"Couldn't load file: "<< fileName <<std::endl;
        return;
    }

    img2 = cvCreateImage(cvSize(img1->height, img1->height), IPL_DEPTH_8U, 1);

    // Pobierz właściwości obrazu
    width = img1->width;
    height = img1->height;
    step = img1->widthStep;

    img1_data = (uchar*)img1->imageData;
    img2_data = (uchar*)img2->imageData;

    // Inicjalizacja tablic dla operacji fftw 
    data_in = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * width * height);
    fft = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * width * height);
    ifft = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * width * height);

    // Stwórz plan
    plan_f = fftw_plan_dft_1d(width * height, data_in, fft, FFTW_FORWARD, FFTW_ESTIMATE);
    plan_b = fftw_plan_dft_1d(width * height, fft, ifft, FFTW_BACKWARD, FFTW_ESTIMATE);

    // Wczytaj dane z img1_data do fftw 
    for(int i = 0, k = 0; i < height; i++){
        for(int j = 0; j < width; j++){
            data_in[k][0] = (double)img1_data[i * step + j];
            data_in[k][1] = 0.0;
            k++;
        }
    }

    // Przeprowadź FFT
    fftw_execute(plan_f);


    /*
	Wydaje mi się że w tym miejscu należy zastosować filtry
	na 'fft'	
    */
	

    // Przeprowadź IFFT
    fftw_execute(plan_b);

    // Normalizacja wyników IFFT 
    for(int i = 0; i < (width * height); i++){
        ifft[i][0] /= (double)(width * height);
    }

    // Kopiowanie wyników IFFT do img2_data
    for(int i = 0, k = 0; i < height; i++){
        for(int j = 0; j < width; j++){
            img2_data[i * step + j] = (uchar)ifft[k++][0];
        }
    }


    // Wyświetl obrazy
    cvNamedWindow("Obraz", CV_WINDOW_AUTOSIZE);
    cvNamedWindow("IFFT", CV_WINDOW_AUTOSIZE);
    cvShowImage("Obraz", img1);
    cvShowImage("IFFT", img2);

    cvWaitKey(0);

    // Zwolnij pamięć
    cvDestroyWindow("Obraz");
    cvDestroyWindow("IFFT");

}

Problem jest taki, że zabardzo nie wiem jak dany filtr zaimplementować.

0

skoro po zrobieniu transformaty masz funkcje ktorej argumentem jest czestotliwosc to znaczy ze wystarczy przemnozyc kolejne probki przez coraz mniejsze wartosci (dla filtru dolno przepustowego). Np mozesz zaczac od 1 a skonczyc na zerze lub przemnozyc 1/3 wektora przez 1 a kolejne 2/3 przez 0. najlepiej gdyby wartosci przez ktore mnozysz mialy ksztalt cos w stylu arctg. musisz tylko pamietac ze podczas robienia odwrotnej transformaty po takim filtrze moze sie zdarzyc ze niektore probki wyjda zespolone (wtedy nalezy wziac czesc rzeczywista tej liczby lub jej modul - czesc zespolona bedzie dosc mala, wiec nie bedzie mialo to zbytnio znaczenia). filtr dolnoprzepustowy moze byc funkcją np: 1/(Tx+1), gdzie T to jest jakas stala ktora musisz sobie dopasowac, a x to numer probki. Najlepszy efekt uzyskasz jak sobie ten filtr sam zaprojektrujesz w miare potrzeb. Ja bym na Twoim raczej poczytał coś o wykrywaniu krawędzi, później o wykryciu w którym miejscu jest rejestracja samochodu i pociął ją jakoś na cyfry (ew. zrobienie tego na początku), następnie użył sieci neuronowej do wykrycia jaka to rejestracja

0

Dzięki za odpowiedź.

0
kojas22 napisał(a)

Witam!
Pracuje aktualnie nad algorytmem który ma za zadanie "wykryć" na obrazie wejściowym rejestrację samochodową (temat pracy licencjackiej) . Po przeprowadzeniu szybkiej transformaty fouriera i otrzymaniu widma obrazu chcę na tym widmie zastosować filtr górnoprzepustowy lub dolnoprzepustowy i wykonać odwrotną transformate fouriera aby zobaczyć jak będzie wyglądał obraz po zastosowaniu filtrów.

Korzystam przy tym z biblioteki OpenCV, fftw3, Qt 4.7.

A o to co mam:

////////////////////////////////////////////////////////////////////////*/ converter.h *//////////////////

 

#ifndef CONVERTER_H
#define CONVERTER_H

#include <iostream>
#include <fftw3.h>
#include <cv.h>
#include <highgui.h>


#include <QImage>
#include <QPixmap>
#include <QPicture>
#include <QRgb>

using namespace cv;


class Converter{
public:
    Converter();
    ~Converter();

    QImage makeN2Dimension(const QImage qImage);
    void transform(char* fileName);

private:
    IplImage *img1;
    IplImage *img2;

    uchar *img1_data;
    uchar *img2_data;

    fftw_complex *data_in;
    fftw_complex *fft;
    fftw_complex *ifft;

    fftw_plan plan_f;
    fftw_plan plan_b;

    int width, height, step;

};

#endif // CONVERTER_H

////////////////////////////////////////////////////////////////////////*/ converter.cpp *//////////////

 

#include <converter.h>

// Konstructor
Converter::Converter(){
    img1 = 0;
    img2 = 0;
    data_in = 0;
    fft = 0;
    ifft = 0;
    plan_f = 0;
    plan_b = 0;
}

// Destructor
Converter::~Converter(){

    // Zwolnij pamięć
    if(img1 != 0)
        cvReleaseImage(&img1);

    if(img2 != 0)
        cvReleaseImage(&img2);

    if(plan_f != 0)
        fftw_destroy_plan(plan_f);

    if(plan_b != 0)
        fftw_destroy_plan(plan_b);

    if(data_in != 0)
        fftw_free( data_in );

    if(fft != 0)
        fftw_free( fft );

    if(ifft != 0)
        fftw_free( ifft );
}

// Dopełnia obraz tak aby boki były tej samej długości
QImage Converter::makeN2Dimension(const QImage qImage){

    QImage n2Image;

    int h = qImage.height();
    int w = qImage.width();

    if(w == h) return qImage;

    if(w == 0 || h == 0) return QImage(100, 100, QImage::Format_RGB888);

    w > h ? n2Image = QImage(w, w, QImage::Format_RGB888) :
            n2Image = QImage(h, h, QImage::Format_RGB888);

        for(int i = 0; i < w; i++)
            for(int j = 0; j < h; j++)
             n2Image.setPixel(i,j, qImage.pixel(i,j));

    return n2Image;
}

void Converter::transform(char* fileName){

    // Wczytaj orginalny obraz
    img1 = cvLoadImage(fileName, CV_LOAD_IMAGE_GRAYSCALE);

    // Sprawdź plik
    if(fileName == 0){
        std::cout<<"Couldn't load file: "<< fileName <<std::endl;
        return;
    }

    img2 = cvCreateImage(cvSize(img1->height, img1->height), IPL_DEPTH_8U, 1);

    // Pobierz właściwości obrazu
    width = img1->width;
    height = img1->height;
    step = img1->widthStep;

    img1_data = (uchar*)img1->imageData;
    img2_data = (uchar*)img2->imageData;

    // Inicjalizacja tablic dla operacji fftw 
    data_in = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * width * height);
    fft = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * width * height);
    ifft = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * width * height);

    // Stwórz plan
    plan_f = fftw_plan_dft_1d(width * height, data_in, fft, FFTW_FORWARD, FFTW_ESTIMATE);
    plan_b = fftw_plan_dft_1d(width * height, fft, ifft, FFTW_BACKWARD, FFTW_ESTIMATE);

    // Wczytaj dane z img1_data do fftw 
    for(int i = 0, k = 0; i < height; i++){
        for(int j = 0; j < width; j++){
            data_in[k][0] = (double)img1_data[i * step + j];
            data_in[k][1] = 0.0;
            k++;
        }
    }

    // Przeprowadź FFT
    fftw_execute(plan_f);


    /*
	Wydaje mi się że w tym miejscu należy zastosować filtry
	na 'fft'	
    */
	

    // Przeprowadź IFFT
    fftw_execute(plan_b);

    // Normalizacja wyników IFFT 
    for(int i = 0; i < (width * height); i++){
        ifft[i][0] /= (double)(width * height);
    }

    // Kopiowanie wyników IFFT do img2_data
    for(int i = 0, k = 0; i < height; i++){
        for(int j = 0; j < width; j++){
            img2_data[i * step + j] = (uchar)ifft[k++][0];
        }
    }


    // Wyświetl obrazy
    cvNamedWindow("Obraz", CV_WINDOW_AUTOSIZE);
    cvNamedWindow("IFFT", CV_WINDOW_AUTOSIZE);
    cvShowImage("Obraz", img1);
    cvShowImage("IFFT", img2);

    cvWaitKey(0);

    // Zwolnij pamięć
    cvDestroyWindow("Obraz");
    cvDestroyWindow("IFFT");

}

Problem jest taki, że zabardzo nie wiem jak dany filtr zaimplementować.

0

Temat do zamknięcia, już sobie z tym poradziłem.

1 użytkowników online, w tym zalogowanych: 0, gości: 1