LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Applying median filter to a picture ... (https://www.linuxquestions.org/questions/programming-9/applying-median-filter-to-a-picture-430357/)

tomazN 03-31-2006 11:44 AM

Applying median filter to a picture ...
 
Somebody has a working median filter for gray and color images written in C or C++ and can share it ? I made a simple QT interface to load picture, now i want to make a median filter to that picture. But i have no ideer how to do that :( Don`t have alot experience in picture processing.

I can also give the code for my interface if asked, im willling to share it (well its not much anyway).

Gratefull for help.

paulsm4 03-31-2006 12:41 PM

Take a look at ImageMagick:
http://www.imagemagick.org/Magick++/
http://www.imagemagick.org/script/magick-wand.php
http://www.imagemagick.org/script/magick-core.php

'Hope that helps .. PSM

tomazN 03-31-2006 01:22 PM

I have to use language C++ or C (with standard libs) and QT to implement them to my GUI. So extra software or programs dont count. Its a school project, which i am scared i am not gona make without some help :cry:

Well here is what i made so far:

main.cpp

Code:

#include <QApplication>
#include <QImageWriter>
#include "imageviewer.h"

int main(int argc, char *argv[])
{
        QApplication app(argc, argv);
        ImageViewer imageViewer;
        imageViewer.show();
        return app.exec();
}

imageviewer.h

Code:

#ifndef IMAGEVIEWER_H
#define IMAGEVIEWER_H

#include <QMainWindow>
#include <QPrinter>
#include <QImageWriter>
#include <QImage>

class QAction;
class QLabel;
class QMenu;
class QScrollArea;
class QScrollBar;

class ImageViewer : public QMainWindow
{
        Q_OBJECT

        public:
        ImageViewer();

        private slots:
        void open();
        void save();
        void reload();
        void zoomIn();
        void zoomOut();
        void normalSize();
        void fitToWindow();
        void bw();
        void mediana();
        void about();

        private:
        void createActions();
        void createMenus();
        void updateActions();
        void scaleImage(double factor);
        void adjustScrollBar(QScrollBar *scrollBar, double factor);

        QLabel *imageLabel;
        QImage image;
        QString fileName;
        QScrollArea *scrollArea;
        double scaleFactor;

        QPrinter printer;

        QAction *openAct;
        QAction *saveAct;
        QAction *reloadAct;
        QAction *exitAct;
        QAction *zoomInAct;
        QAction *zoomOutAct;
        QAction *normalSizeAct;
        QAction *fitToWindowAct;
        QAction *bwAct;
        QAction *medianaAct;
        QAction *aboutAct;

        QMenu *fileMenu;
        QMenu *viewMenu;
        QMenu *filterMenu;
        QMenu *helpMenu;
};
#endif

imageviewer.cpp

Code:

#include <QtGui>
#include <QImageWriter>
#include "imageviewer.h"

ImageViewer::ImageViewer()
{
        imageLabel = new QLabel;
        imageLabel->setBackgroundRole(QPalette::Base);
        imageLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
        imageLabel->setScaledContents(true);

        scrollArea = new QScrollArea;
        scrollArea->setBackgroundRole(QPalette::Mid);
        scrollArea->setWidget(imageLabel);
        setCentralWidget(scrollArea);
       
        createActions();
        createMenus();
       
        setWindowTitle(tr("Obdelava in Analiza slik"));
        resize(500, 400);
}

void ImageViewer::open()
{
        QString filter;
        QString selectedFilter;
        QList<QByteArray> formats = QImageWriter::supportedImageFormats();
        foreach (QString format, formats)
        {
                filter += QString("%1 files (*.%2);;").arg(format.toUpper()).arg(format);
        }

        // remove unnecessary chars from the end of the filter
        if (filter.endsWith(";;"))
        {
                filter.chop(2);
        }
       
        QString fileName = QFileDialog::getOpenFileName(this,tr("Open File"), QDir::currentPath(), filter, &selectedFilter);
        if (!fileName.isEmpty())
        {
                image.load(fileName);
                if (image.isNull())
                {
                        QMessageBox::information(this, tr("ImageViewer"), tr("Cannot load %1.").arg(fileName));
                return;
                }
        imageLabel->setPixmap(QPixmap::fromImage(image));
        scaleFactor = 1.0;

        saveAct->setEnabled(true);
        fitToWindowAct->setEnabled(true);
        updateActions();

        if (!fitToWindowAct->isChecked())
                imageLabel->adjustSize();
        }
}

void ImageViewer::save()
{
        // construct a filter of all supported formats
        QString filter;
        QList<QByteArray> formats = QImageWriter::supportedImageFormats();
        foreach (QString format, formats)
        {
                filter += QString("%1 files (*.%2);;").arg(format.toUpper()).arg(format);
        }

        // remove unnecessary chars from the end of the filter
        if (filter.endsWith(";;"))
        {
                filter.chop(2);
        }

        // get save file name
        QString selectedFilter;
        QString s = QFileDialog::getSaveFileName(this, "Save image as", QDir::currentPath(), filter, &selectedFilter);

        if (!s.isEmpty())
            {

        // check for the selected format
        QString format = selectedFilter.split(" ").at(0);
        QFileInfo fi(s);

        if (!fi.suffix().endsWith(format, Qt::CaseInsensitive))
        {
                // remove possible incorrect suffix
                s.chop(fi.suffix().length());
                // set correct suffix
                s += "." + format.toLower();
        }

        // save image in the selected format
        if (!image.save(s, format.toAscii().constData()))
        {
                QMessageBox::information(this, "Image Viewer", QString("Unable to save %1.").arg(s));
        }
        }
}

void ImageViewer::zoomIn()
{
        scaleImage(1.25);
}

void ImageViewer::zoomOut()
{
        scaleImage(0.8);
}

void ImageViewer::normalSize()
{
        imageLabel->adjustSize();
        scaleFactor = 1.0;
}

void ImageViewer::fitToWindow()
{
        bool fitToWindow = fitToWindowAct->isChecked();
        scrollArea->setWidgetResizable(fitToWindow);
        if (!fitToWindow)
        {
                normalSize();
        }
        updateActions();
}

void ImageViewer::about()
{
        QMessageBox::about(this, tr("About"),
        tr("<h2>Obdelava in Analiza slik</h2>"
        "<p>Copyright &copy; 2006 Novak Tomaz"
        "<p>Obdelava in Analiza slik je program za pomoc pri obdelavi in slik."));
}

void ImageViewer::createActions()
{
        openAct = new QAction(tr("&Open..."), this);
        openAct->setShortcut(tr("Ctrl+O"));
        connect(openAct, SIGNAL(triggered()), this, SLOT(open()));

        saveAct = new QAction(tr("&Save..."), this);
        saveAct->setShortcut(tr("Ctrl+S"));
        saveAct->setEnabled(false);
        connect(saveAct, SIGNAL(triggered()), this, SLOT(save()));

        reloadAct = new QAction(tr("&Reload Image..."), this);
        reloadAct->setShortcut(tr("Ctrl+R"));
        connect(reloadAct, SIGNAL(triggered()), this, SLOT(reload()));

        exitAct = new QAction(tr("E&xit"), this);
        exitAct->setShortcut(tr("Ctrl+Q"));
        connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));

        zoomInAct = new QAction(tr("Zoom &In (25%)"), this);
        zoomInAct->setShortcut(tr("Ctrl++"));
        zoomInAct->setEnabled(false);
        connect(zoomInAct, SIGNAL(triggered()), this, SLOT(zoomIn()));

        zoomOutAct = new QAction(tr("Zoom &Out (25%)"), this);
        zoomOutAct->setShortcut(tr("Ctrl+-"));
        zoomOutAct->setEnabled(false);
        connect(zoomOutAct, SIGNAL(triggered()), this, SLOT(zoomOut()));

        normalSizeAct = new QAction(tr("&Normal Size"), this);
        normalSizeAct->setShortcut(tr("Ctrl+S"));
        normalSizeAct->setEnabled(false);
        connect(normalSizeAct, SIGNAL(triggered()), this, SLOT(normalSize()));
       
        fitToWindowAct = new QAction(tr("&Fit to Window"), this);
        fitToWindowAct->setEnabled(false);
        fitToWindowAct->setCheckable(true);
        fitToWindowAct->setShortcut(tr("Ctrl+F"));
        connect(fitToWindowAct, SIGNAL(triggered()), this, SLOT(fitToWindow()));

        bwAct = new QAction(tr("Black &White"), this);
        bwAct->setShortcut(tr("Ctrl+B"));
        connect(bwAct, SIGNAL(triggered()), this, SLOT(bw()));

        medianaAct = new QAction(tr("&Mediana"), this);
        medianaAct->setShortcut(tr("Ctrl+M"));
        connect(medianaAct, SIGNAL(triggered()), this, SLOT(mediana()));
       
        aboutAct = new QAction(tr("&About"), this);
        connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
}

void ImageViewer::createMenus()
{
        fileMenu = new QMenu(tr("&File"), this);
        fileMenu->addAction(openAct);
        fileMenu->addAction(saveAct);
        fileMenu->addSeparator();
        fileMenu->addAction(reloadAct);
        fileMenu->addSeparator();
        fileMenu->addAction(exitAct);
       
        viewMenu = new QMenu(tr("&View"), this);
        viewMenu->addAction(zoomInAct);
        viewMenu->addAction(zoomOutAct);
        viewMenu->addAction(normalSizeAct);
        viewMenu->addSeparator();
        viewMenu->addAction(fitToWindowAct);

        filterMenu = new QMenu(tr("&Filters"), this);
        filterMenu->addAction(bwAct);
        filterMenu->addAction(medianaAct);
       
        helpMenu = new QMenu(tr("&Help"), this);
        helpMenu->addAction(aboutAct);
       
        menuBar()->addMenu(fileMenu);
        menuBar()->addMenu(viewMenu);
        menuBar()->addMenu(filterMenu);
        menuBar()->addMenu(helpMenu);
}

void ImageViewer::bw()
{
}

void ImageViewer::mediana()
{
}

void ImageViewer::reload()
{
        image.load(fileName);
        imageLabel->setPixmap(QPixmap::fromImage(image));
        scaleFactor = 1.0;

        saveAct->setEnabled(true);
        fitToWindowAct->setEnabled(true);
        updateActions();

        if (!fitToWindowAct->isChecked())
                imageLabel->adjustSize();
}

void ImageViewer::updateActions()
{
        zoomInAct->setEnabled(!fitToWindowAct->isChecked());
        zoomOutAct->setEnabled(!fitToWindowAct->isChecked());
        normalSizeAct->setEnabled(!fitToWindowAct->isChecked());
}

void ImageViewer::scaleImage(double factor)
{
        Q_ASSERT(imageLabel->pixmap());
        scaleFactor *= factor;
        imageLabel->resize(scaleFactor * imageLabel->pixmap()->size());
       
        adjustScrollBar(scrollArea->horizontalScrollBar(), factor);
        adjustScrollBar(scrollArea->verticalScrollBar(), factor);
       
        zoomInAct->setEnabled(scaleFactor < 3.0);
        zoomOutAct->setEnabled(scaleFactor > 0.333);
}

void ImageViewer::adjustScrollBar(QScrollBar *scrollBar, double factor)
{
scrollBar->setValue(int(factor * scrollBar->value() + ((factor - 1) * scrollBar->pageStep()/2)));
}

Sorry for long post. This is a GUI that can open image, save it back, reload it, scale, zoom in, zoom out, fit to window. Now im stuck with making median filter so i can apply it to that image. Or atleast some example of something done to that image, so i get a grasp how i can get to the pixels, and make something with them.

Im not lazy in any way, i just cant figure this one out :(
Never had a spot for C++ or C, and never we done any work on image processing so i even dont have the right knowledge how things go.

If you can help, well probably thx is not enough, but you would realy help me out.

Well here it goes. thx.

paulsm4 03-31-2006 02:11 PM

Of *COURSE* you want to use a library like ImageMagick, if at all possible.

When you're a professional, do you think you'll have the luxury of re-inventing the wheel?

The whole beauty of Open Source is that you can see how somebody did something (instead of just buying or licensing closed, "black boxes" like in the commercial world) which (in theory, at least) will educate and empower you to ultimately make your own contributions back to the open source community.

Please ask your professor if you can use a library like ImageMagick (or GTK+, or any number of other alternatives) in your project:

a) If he/she says "yes", please make the extra effort to look into the ImageMagick source and figure out how the particular filter you're using actually works. Make sure your professor knows you took that effort.

b) If he/she says "no", then get a book from the library on "Image Processing 101", read what you need, and post back any specific questions you have about the median filter (or convolution filter, or color quantization, or whatever you happen to be working with).

If you wind up having to "reinvent the wheel", then take it one piece at a time, and post back specific questions about that one piece.

'Hope that helps .. PSM

tomazN 04-01-2006 02:31 AM

I have to implement it myself into that code i posted. So it works in my QT GUI i made. Well its not so hard i know how median filter works. I am just stuck, how do i acess pixels with QT so i can use them in my algorithm. So i have to acess pixels. Maybe someone can wrote me a simple example of acessing pixels, and then making dunno each pixel -5 and then write them back to the picture, so i get how i do those steps, i can do the rest myself.

thx.

paulsm4 04-01-2006 11:34 AM

Real question: "how to access pixels in Qt?"
 
Hi -

So the real question is:
Quote:

how do i acess pixels with QT so i can use them in my algorithm?
That's different ;-)

Lots of ways, including:

http://doc.trolltech.com/3.3/qpixmap.html

http://doc.trolltech.com/3.3/qcanvaspixmaparray.html

http://www.jtz.org.pl/Inne/QT-Tutorial/qimage.html

http://dot.kde.org/1098950311/

tomazN 04-02-2006 02:29 PM

Can you make some simple example how to implement that, im not the brightest when i have to read some manual for some programming language, and not realy good at QT or C++ so i understand hard whats going on, good in java but thats a completly diffrent approach :S

Thx.

tomazN 04-03-2006 05:15 AM

Ok got filter mediana for black and white pictures.

/***************************************************************************
* Func: median_filt *
* *
* Desc: median filters an image using a block mask *
* *
* Params: source - pointer to image in memory *
* cols - number of columns in image *
* rows - number of rows in image *
* filename - name of output file *
* side - width of block *
***************************************************************************/

void median_filt(image_ptr source, int cols, int rows, char *filename,int side)

Now i need to supply it with these parameters. I got cols and rows from image.width(); and image.height(); filename i specify, it will be filename to which picture will be saved. Now i dunno how do i get width of block in QT, or what width of block actualy is. And source says its pointer to image in memory. Can i make a pointer in QT to image to memory (notice that the algorithm for mediana is written in C, compiles fine), or how do i make a pointer to image ? If i have QImage image; How can i make pointer to location of that ?

Thx.


All times are GMT -5. The time now is 03:16 PM.