#include "cvImage.h" //#include "opencv2/imgproc/imgproc.hpp" using namespace cv; cvImage::cvImage() : _menu(NULL), _image(NULL) { setWindowTitle(tr("Egaliseur de contraste couleur")); resize(480, 240); _menu = new QMenu("File"); _menu->addAction("Op3n", this, SLOT(_open())); _menu->addSeparator(); _menu->addAction("Source", this, SLOT(_rgbView())); _menu->addSeparator(); _menu->addAction("HSV", this, SLOT(_hsvView())); _menu->addSeparator(); _menu->addAction("Histograme", this, SLOT(_histcalc())); _menu->addSeparator(); _menu->addAction("Save", this, SLOT(_save())); _menu->addSeparator(); _menu->addAction("Exit", this, SLOT(close())); _menu_bar.addMenu(_menu); _menu = new QMenu("Egalisation de contraste"); _menu->addAction("Naif", this, SLOT(_egalizeH())); _menu->addAction("Naif+", this, SLOT(_egalizeH3())); _menu->addAction("HSU", this, SLOT(_egalizeH2())); _menu->addSeparator(); _menu->addAction("diff orginal et Naif", this, SLOT(_diff())); _menu->addAction("diff Naif et Naif+", this, SLOT(_diff1())); _menu->addAction("diff Naif et HSU", this, SLOT(_diff2())); _menu_bar.addMenu(_menu); setMenuBar(&_menu_bar); _onglet.setParent(this); // _onglet->tabBar()->setPalette(*(new QPalette(Qt::white))); setCentralWidget(&_onglet); } cvImage::~cvImage() { if (_menu) delete _menu; if (_image) delete _image; } void cvImage::Mat2QImage(cv::Mat const& src, QImage* dest ) { cv::Mat temp(src); cvtColor(src, temp,COLOR_BGR2RGB); if (dest) { delete dest; } dest= new QImage(temp.size().width, temp.size().height, QImage::Format_RGB888); // Copy cv::Mat to QImage memcpy(dest->scanLine(0), (unsigned char*)temp.data, dest->width() * dest->height() * temp.channels()); //return dest; } void cvImage::QImage2Mat(QImage* const& src, cv::Mat& res) { QImage temp = src->copy(); res=cv::Mat(temp.height(),temp.width(),CV_8UC3,(uchar*)temp.bits(),temp.bytesPerLine()); cvtColor(res, res,COLOR_RGB2BGR); //return res; } void cvImage::paintEvent(QPaintEvent* e) { //_onglet->children(); //get the list of tab //QList widgets =_onglet->children(); // ajout2->setParent(_onglet); // _onglet->addTab(ajout,"Visuel"); //_onglet->addTab(ajout1,"Histograme 2D"); // _onglet->addTab(ajout2,"Histogramme 3D"); /* QWidget * widgets = _onglet->widget(0); QWidget * widgets1 = _onglet->widget(1); QWidget * widgets2 = _onglet->widget(2); if(!widgets) return; QPainter painter(widgets); */ // When no image has been loaded, there's nothing to draw. if (!_image) return; // painter.drawImage(QPoint(0, 0), *_image); // widgets->resize(_image->size()); _onglet.setImg(_image); // _onglet->setHist(_hist); QWidget::paintEvent(e); } void cvImage::_open() { // Display dialog so the user can select a file QString filename = QFileDialog::getOpenFileName(this,tr("Open Image"),QDir::currentPath(),tr("Files (*.png *.jpg *.tiff *.bmp *.pgm)")); if (filename.isEmpty()) // Do nothing if filename is empty return; cv::Mat img = cv::imread(filename.toStdString()); if (img.empty()) return; cvtColor(img, img,COLOR_BGR2RGB); _img=img; // _image is created according to video dimensions if (_image) { delete _image; } _image = new QImage(img.size().width, img.size().height, QImage::Format_RGB888); // Copy cv::Mat to QImage memcpy(_image->scanLine(0), (unsigned char*)img.data, _image->width() * _image->height() * img.channels()); //Mat2QImage(img, _image); // Set the filename as the window title this->statusBar()->setStatusTip(filename); // Resize the window to fit video dimensions resize(img.size().width, img.size().height); // Mouse move events will occur only when a mouse button is pressed down, // unless mouse tracking has been enabled: QWidget::setMouseTracking(true); // Trigger paint event to redraw the window update(); } void cvImage::_rgbView() { if (_img.empty() ) // pas d'image charger ne rien fair return; // l'image exite if (!_img.empty() && _image) { delete _image; _image = new QImage( _img.data, _img.size().width, _img.size().height, _img.step, QImage::Format_RGB888); // Resize the window to fit video dimensions resize(_img.size().width, _img.size().height); /* cv::Mat rgb,hsv,dst; cv::cvtColor(_img,rgb,CV_RGB2BGR); cv::cvtColor(_img,hsv,CV_RGB2HSV); cv::hconcat(rgb,hsv,dst); cv::namedWindow( "Source", 1 ); cv::imshow( "Source", dst ); */ } update(); } void cvImage::_hsvView() { if (_img.empty() ) // pas d'image charger ne rien fair return; // l'image exite if (!_img.empty() && _image) { delete _image; cv::Mat hsv, hsvI; cv::cvtColor(_img,hsv,COLOR_RGB2HSV); // on permute V et H pour visualisation dans Qimage // mapage bgr d'onpencv -> permutation pour que les affiche soit corect std::vector tmp; cv::split(hsv,tmp); hsvI=tmp[0]; tmp[0]=tmp[2]; tmp[2]=hsvI; cv::merge(tmp,hsvI); cv::namedWindow( "HSV", 1 ); cv::imshow( "HSV", hsv ); _image = new QImage( hsvI.data, hsvI.size().width, hsvI.size().height, hsvI.step, QImage::Format_RGB888); // Resize the window to fit video dimensions resize(hsvI.size().width, hsvI.size().height); update(); } } void cvImage::_save() { if (_img.empty()) return; cv::Mat tmp; cv::cvtColor(_img,tmp,COLOR_RGB2BGR); cv::imwrite("src.jpg",tmp); cv::cvtColor(_img,tmp,COLOR_RGB2HSV); cv::imwrite("src_HSV.jpg",tmp); if (!_img_eq_rgb.empty()){ cv::cvtColor(_img_eq_rgb,tmp,COLOR_RGB2BGR); cv::imwrite("egalisation_rgb.jpg",tmp);} if (!_img_eq_rgb1.empty()){ cv::cvtColor(_img_eq_rgb1,tmp,COLOR_RGB2BGR);; cv::imwrite("egalisation_rgb1.jpg",tmp);} } void cvImage::keyPressEvent(QKeyEvent* event) { switch (event->key()) { // ESC: exit application case Qt::Key_Escape: { close(); } break; } } void cvImage::mouseMoveEvent(QMouseEvent *event) { if (!_image) return; QPoint pos = event->pos(); if (pos.x() < 10 || pos.x() >= _image->width()+10) return; if (pos.y() < 30 || pos.y() >= _image->height()+30) return; QString pos_x; pos_x = pos_x.setNum(pos.x() -10 ); QString pos_y; pos_y = pos_y.setNum(pos.y()-30); QColor pixel(_image->pixel(pos_x.toDouble(),pos_y.toDouble())); int r = pixel.red(); int g = pixel.green(); int b = pixel.blue(); QString pixel_info = pos_x + "," + pos_y + " R:" + QString().setNum(r) + " G:" + QString().setNum(g) + " B:" + QString().setNum(b); // TODO: set pixel info on status bar instead of window title this->statusBar()->setStatusTip(pixel_info); //setWindowTitle(pixel_info); qDebug() << "cvImage::mouseMoveEvent " << pixel_info; } void cvImage::_close() { emit closed(); } /************************************************* * * * * * * ************************************************/ void cvImage::calculHist(cv::Mat& image , int* hist) { int i; /* initialisation de l'histogramme a 0*/ for(i = 0; i < 256;i++) hist[i]=0; /* calcule des valeur de l'histogramme */ for(i = 0; i < image.cols*image.rows; i++) hist[image.data[i]]++; } void cvImage::calculHist3(const std::vector& image , int* hist) { int i,p; /* initialisation de l'histogramme a 0*/ for(i = 0; i < 256;i++) hist[i]=0; /* calcule des valeur de l'histogramme */ // for(std::vector::iterator i = mv.begin(); i != mv.end();i++) for(p = 0; p < image[0].cols*image[0].rows; p++) hist[(image[0].data[p]+image[1].data[p]+image[2].data[p])/3]++; } void cvImage::egalizhist(cv::Mat& imSrc, cv::Mat& imDst) { int i; double n; //if (imSrc.size == imDst->size) /* controle des dimention des image*/ // { int histEg[256],histCum[256]; calculHist(imSrc, histEg); /*calcule de l'histogramme cumulé*/ for(i=0; i<256; i++) if(i!=0) histCum[i]= histCum[i-1] + histEg[i]; else histCum[i]= histEg[i]; n= (double)histCum[255]; /* nb pixel dans l'image*/ for(i=0; i<256; i++) histEg[i]= 255* (histCum[i]/n) ; for(i=0; i< imDst.cols * imDst.rows ; i++) imDst.data[i]= (uchar ) histEg[ imSrc.data[i] ]; //} } void cvImage::egalizhist3(const std::vector& imSrc, std::vector& imDst) { int i; double n; int histEg[256],histCum[256]; calculHist3(imSrc, histEg); /*calcule de l'histogramme cumulé*/ for(i=0; i<256; i++) if(i!=0) histCum[i]= histCum[i-1] + histEg[i]; else histCum[i]= histEg[i]; n= (double)histCum[255]; /* nb pixel dans l'image*/ for(i=0; i<256; i++) histEg[i]= 255* (histCum[i]/n) ; for(i=0; i< imDst[0].cols * imDst[0].rows ; i++){ imDst[0].data[i]= (uchar ) histEg[ imSrc[0].data[i] ]; imDst[1].data[i]= (uchar ) histEg[ imSrc[1].data[i] ]; imDst[2].data[i]= (uchar ) histEg[ imSrc[2].data[i] ]; } } void cvImage::_egalizeH() { /* * on egalalise les canneau independament les un des autres * * */ if (_img.empty()) return; std::vector mv,v;//[_img.channels()]; cv::split(_img,mv); for(std::vector::iterator i = mv.begin(); i != mv.end();i++) egalizhist( *i, *i); cv::Mat merge; cv::merge(mv,merge); _img_eq_rgb=merge; if(_image) delete _image; _image = new QImage( merge.data,merge.size().width, merge.size().height, merge.step, QImage::Format_RGB888); _imgHeq1=merge; // Resize the window to fit video dimensions resize(merge.size().width, merge.size().height); update(); } void cvImage::_egalizeH3() { /* * on egalalise les canneau fonction de l'intensité du pixel i=(r+v+b)/3 * * */ if (_img.empty()) return; std::vector mv_src, mv_dst; cv::split(_img,mv_src); cv::split(_img,mv_dst); // for(std::vector::iterator i = mv.begin(); i != mv.end();i++) //egalizhist( *i, *i); egalizhist3(mv_src,mv_dst); cv::Mat merge; cv::merge(mv_dst,merge); _img_eq_rgb1=merge; if(_image) delete _image; _image = new QImage( merge.data,merge.size().width, merge.size().height, merge.step, QImage::Format_RGB888); _imgHeq1=merge; // Resize the window to fit video dimensions resize(merge.size().width, merge.size().height); update(); } void cvImage::_egalizeH2(){ if(!_img.data ) return; cv::Mat src,hsv; cv::cvtColor(_img, src, COLOR_RGB2BGR); cv::cvtColor(src, hsv, COLOR_BGR2HSV); // Quantize the hue to 30 levels // and the saturation to 32 levels int hbins = 30, sbins = 32; int histSize[] = {hbins, sbins}; // hue varies from 0 to 179, see cvtColor float hranges[] = { 0, 180 }; // saturation varies from 0 (black-gray-white) to // 255 (pure spectrum color) float sranges[] = { 0, 256 }; const float* ranges[] = { hranges, sranges }; cv::MatND hist; // we compute the histogram from the 0-th and 1-st channels int channels[] = {0, 1}; cv::calcHist( &hsv, 1, channels, cv::Mat(), // do not use mask hist, 2, histSize, ranges, true, // the histogram is uniform false ); double maxVal=0; cv::minMaxLoc(hist, 0, &maxVal, 0, 0); int scale = 10; cv::Mat histImg = cv::Mat::zeros(sbins*scale, hbins*10, CV_8UC3); for( int h = 0; h < hbins; h++ ) for( int s = 0; s < sbins; s++ ) { float binVal = hist.at(h, s); int intensity = cvRound(binVal*255/maxVal); cv::rectangle( histImg, cv::Point(h*scale, s*scale), cv::Point( (h+1)*scale - 1, (s+1)*scale - 1), cv::Scalar::all(intensity), cv::FILLED ); } _image = new QImage( src.data,src.size().width, src.size().height, src.step, QImage::Format_RGB888); } void cvImage::_histcalc(){ if( !_img.data ) return ; Mat src, dst; /// Load image src = _img; /// Separate the image in 3 places ( B, G and R ) std::vector bgr_planes; split( src, bgr_planes ); /// Establish the number of bins int histSize = 256; /// Set the ranges ( for B,G,R) ) float range[] = { 0, 256 } ; const float* histRange = { range }; bool uniform = true; bool accumulate = false; Mat b_hist, g_hist, r_hist; /// Compute the histograms: calcHist( &bgr_planes[0], 1, 0, Mat(), b_hist, 1, &histSize, &histRange, uniform, accumulate ); calcHist( &bgr_planes[1], 1, 0, Mat(), g_hist, 1, &histSize, &histRange, uniform, accumulate ); calcHist( &bgr_planes[2], 1, 0, Mat(), r_hist, 1, &histSize, &histRange, uniform, accumulate ); // Draw the histograms for B, G and R int hist_w = 512; int hist_h = 400; int bin_w = cvRound( (double) hist_w/histSize ); Mat histImage( hist_h, hist_w, CV_8UC3, Scalar( 0,0,0) ); /// Normalize the result to [ 0, histImage.rows ] normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() ); normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() ); normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() ); /// Draw for each channel for( int i = 1; i < histSize; i++ ) { line( histImage, Point( bin_w*(i-1), hist_h - cvRound(b_hist.at(i-1)) ) , Point( bin_w*(i), hist_h - cvRound(b_hist.at(i)) ), Scalar( 255, 0, 0), 2, 8, 0 ); line( histImage, Point( bin_w*(i-1), hist_h - cvRound(g_hist.at(i-1)) ) , Point( bin_w*(i), hist_h - cvRound(g_hist.at(i)) ), Scalar( 0, 255, 0), 2, 8, 0 ); line( histImage, Point( bin_w*(i-1), hist_h - cvRound(r_hist.at(i-1)) ) , Point( bin_w*(i), hist_h - cvRound(r_hist.at(i)) ), Scalar( 0, 0, 255), 2, 8, 0 ); } }