add color space project

This commit is contained in:
thierry_nibert 2026-08-29 23:20:33 +02:00
parent 1da9ae3385
commit f3bbc48696
23 changed files with 7342 additions and 0 deletions

BIN
assets/images/4N.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

BIN
assets/images/4NI.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

BIN
assets/images/IM2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 467 KiB

5916
assets/images/Lenna.pgm Normal file

File diff suppressed because it is too large Load Diff

BIN
assets/images/Lenna.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 463 KiB

BIN
assets/images/LennaM1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

BIN
assets/images/LennaM2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
assets/images/lena_b.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

BIN
assets/images/sk.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
assets/images/sk.pgm Normal file

Binary file not shown.

BIN
assets/images/sk.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

BIN
assets/images/skg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
assets/images/src.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

BIN
assets/images/src_HSV.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

View File

@ -0,0 +1,185 @@
#include <stdio.h>
#include "highgui.h"
#include "cv.h"
/*QImage Thread::Ipl2QImage(const IplImage *newImage)
{
QImage qtemp;
if (newImage && cvGetSize(newImage).width > 0)
{
int x;
int y;
char* data = newImage->imageData;
qtemp= QImage(newImage->width, newImage->height,QImage::Format_RGB32 );
for( y = 0; y < newImage->height; y++, data +=newImage->widthStep )
for( x = 0; x < newImage->width; x++)
{
uint *p = (uint*)qtemp.scanLine (y) + x;
*p = qRgb(data[x * newImage->nChannels+2],
data[x * newImage->nChannels+1],data[x * newImage->nChannels]);
}
}
return qtemp;
}*/
IplImage * toAnaglyph(IplImage * imgLeft, IplImage *imgRight);
int main(int argc, char* argv[] )
{
char key;
IplImage* image= NULL;
CvCapture *capture;
// Ouvrir le flux vidéo
capture =cvCreateCameraCapture(1);
//taille fenetre
cvSetCaptureProperty( capture, CV_CAP_PROP_FRAME_WIDTH, 640 );
cvSetCaptureProperty( capture, CV_CAP_PROP_FRAME_HEIGHT, 480 );
//Vérifier si l'ouverture du flux est ok.cgi
if (!capture )
{
printf("Ouverture du flux vidéo impossible !\n");
return 1;
}
// Définition de la fenêtre
cvNamedWindow("GeckoGeek Window",CV_WINDOW_AUTOSIZE);
cvMoveWindow("GeckoGeek Window", 0, 100);
// Boucle tant que l'utilisateur n'appuie pas sur la touche q (ou Q)
while(key != 'q' )
{
// On récupère une image
image = cvQueryFrame(capture);
// On affiche l'image dans une fenêtre
cvShowImage( "GeckoGeek Window", image);
key = cvWaitKey(10);
}
cvSaveImage (argv[1], image, NULL);
cvReleaseCapture(&capture);
cvDestroyWindow("GeckoGeek Window");
IplImage *image2;
CvCapture *capture2;
capture2 =cvCreateCameraCapture(2);
cvSetCaptureProperty( capture2, CV_CAP_PROP_FRAME_WIDTH, 640 );
cvSetCaptureProperty( capture2, CV_CAP_PROP_FRAME_HEIGHT, 480 );
if (!capture2 )
{
printf("Ouverture du flux vidéo impossible !\n");
return 1;
}
cvNamedWindow("GeckoGeeks Window", CV_WINDOW_AUTOSIZE);
cvMoveWindow("GeckoGeeks Window", 0, 100);
while(key != 'n')
{
image2 = cvQueryFrame(capture2);
cvShowImage( "GeckoGeeks Window", image2);
key = cvWaitKey(10);
}
cvSaveImage (argv[2], image2, NULL);
cvReleaseCapture(&capture2);
cvDestroyWindow("GeckoGeeks Window");
IplImage* imageL= NULL;
IplImage* imageR= NULL;
IplImage* anaglyph= NULL;
/* Vérification des arguments */
if(argc== 4)
{
char* imageMPO = argv[1];
char* imageMPO2 = argv[2];
/* Chargement du fichier image à trasformer */
if ( !(imageL= cvLoadImage(imageMPO, CV_LOAD_IMAGE_UNCHANGED)) )
{
printf( " No image data \n " );
return -1;
}
if ( !(imageR= cvLoadImage(imageMPO2, CV_LOAD_IMAGE_UNCHANGED) ) )
{
printf( " No image data \n " );
return -1;
}
/* trasformation de l'image */
//anaglyph = toAnaglyph( imageL, imageR);
if ( !(anaglyph= toAnaglyph( imageL, imageR) ) )
{
printf( " No anglyphe data \n " );
return -1;
}
cvNamedWindow("Anaglyphe", CV_WINDOW_AUTOSIZE);
cvNamedWindow("Left", CV_WINDOW_AUTOSIZE);
cvNamedWindow("Right", CV_WINDOW_AUTOSIZE);
cvMoveWindow("Left", 0, 100);
cvMoveWindow("Anaglyphe", 450, 100);
cvMoveWindow("Right", 900,100);
//on affiché les image
cvShowImage("Left", imageL);
cvShowImage("Anaglyphe", anaglyph);
cvShowImage("Right", imageR);
// While we don't want to quit
while(key != 'Q' && key != 'q') {
// We wait 10 ms
key = cvWaitKey(10);
}
if (!cvSaveImage (argv[3], anaglyph, NULL))
return -1;
if (!cvSaveImage ("imageL.jpg", imageL, NULL))
return -1;
if (!cvSaveImage("imageR.jpg", imageR, NULL) )
return -1;
cvReleaseImage(&imageL);
cvReleaseImage(&imageR);
cvReleaseImage(&anaglyph);
}
else
{
printf( " Veuillez passer deux image calibrer en paramétre suivie du nom de sortie \n" );
}
return 0;
}
IplImage * toAnaglyph(IplImage * imgLeft, IplImage *imgRight)
{
IplImage *iplReturn;
IplImage *l_R, * l_G, *l_B;
IplImage *r_R, * r_G, *r_B;
iplReturn = cvCreateImage( cvGetSize (imgLeft), 8, 3);
l_R = cvCreateImage( cvGetSize (imgLeft), 8, 1);
l_G = cvCreateImage( cvGetSize (imgLeft), 8, 1);
l_B = cvCreateImage( cvGetSize (imgLeft), 8, 1);
r_R = cvCreateImage( cvGetSize (imgLeft), 8, 1);
r_G = cvCreateImage( cvGetSize (imgLeft), 8, 1);
r_B = cvCreateImage( cvGetSize (imgLeft), 8, 1);
/*sépartion des coleur*/
cvSplit(imgLeft, l_R, l_G, l_B, NULL);
cvSplit(imgRight, r_R, r_G, r_B, NULL);
/*reunion des couleur*/
cvMerge(r_R, r_G, l_B, NULL, iplReturn);
cvReleaseImage(&l_R);
cvReleaseImage(&l_G);
cvReleaseImage(&l_B);
cvReleaseImage(&r_R);
cvReleaseImage(&r_G);
cvReleaseImage(&r_B);
return iplReturn;
}

261
color-space/GLwindow.cpp Normal file
View File

@ -0,0 +1,261 @@
#include "GLwindow.h"
#include <GL/glu.h>
#include <iostream>
#include <QKeyEvent>
#include <QTimer>
#include <QDebug>
GLwindow::GLwindow(QWidget *parent)
: QGLWidget(parent)
{
_width = 0;
_height = 0;
distance = -5.0;
x=0;x_rot = 0.;
y=0;y_rot = 0.;
z=0; z_rot = .0;
// QWidget::setMouseTracking(true);
}
GLwindow::~GLwindow()
{
// glDeleteTextures(1, &_blur_texture);
}
void GLwindow::_tick()
{
/* redisplay */
update(); // triggers paintGL()
QTimer::singleShot(33, this, SLOT(_tick()));
}
void GLwindow::initializeGL()
{
distance = -10.0;
x_rot = 0.;
y_rot = 0.;
z_rot = 0.;
qglClearColor(Qt::darkGray);
glEnable(GL_DEPTH_TEST);
_tick();
}
void GLwindow::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
// Model view matrix
// glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, distance);
glRotatef(x_rot / 16.0f, 1.0f, 0.0f, 0.0f);
glRotatef(y_rot / 16.0f, 0.0f, 1.0f, 0.0f);
glRotatef(z_rot / 16.0f, 0.0f, 0.0f, 1.0f);
// Projection matrix
/* glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0f, 1.0*width()/height(), 0.1f, 100.0f);
*/ //_view_ortho();
_draw();
//_view_perspective();
}
void GLwindow::resizeGL( int width, int height)
{
int side = qMin(width, height);
glViewport((width - side) / 2, (height - side) / 2, side, side);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
#ifdef QT_OPENGL_ES_1
glOrthof(-2, +2, -2, +2, 1.0, 15.0);
#else
glOrtho(-2, +2, -2, +2, 1.0, 15.0);
#endif
glMatrixMode(GL_MODELVIEW);
}
/*************************
*
* Clavier
*
* *********************/
void GLwindow::keyPressEvent(QKeyEvent *event)
{
if(event->key() == Qt::Key_Space){
distance = -10.0;
x_rot = 0.;
y_rot = 0.;
z_rot = 0.;
}
updateGL();// on modifie l'affichage
}
/*************************
*
* Sourie
*
* *********************/
void GLwindow::wheelEvent(QWheelEvent *event)
{
distance *= 1.0 + (1.0 * event->delta() / 1200.0);
updateGL();
}
void GLwindow::mousePressEvent(QMouseEvent *event)
{
last_pos = event->pos();
// qDebug() <<last_pos;
}
void GLwindow::mouseMoveEvent(QMouseEvent *event)
{
int dx = event->x() - last_pos.x();
int dy = event->y() - last_pos.y();
if (event->buttons() & Qt::LeftButton) {
setXRotation(x_rot + 8 * dy);
setYRotation(y_rot + 8 * dx);
} else if (event->buttons() & Qt::RightButton) {
setXRotation(x_rot + 8 * dy);
setZRotation(z_rot + 8 * dx);
} else if (event->buttons() & Qt::MiddleButton) {
distance = -10.0;
x_rot = 0.;
y_rot = 0.;
z_rot = 0.;
}
last_pos = event->pos();
// qDebug()<<last_pos;
}
static void qNormalizeAngle(int &angle)
{
while (angle < 0)
angle += 360 * 16;
while (angle > 360)
angle -= 360 * 16;
}
void GLwindow::setXRotation(int angle)
{
qNormalizeAngle(angle);
if (angle != x_rot) {
x_rot = angle;
//emit xRotationChanged(angle);
updateGL();
}
}
void GLwindow::setYRotation(int angle)
{
qNormalizeAngle(angle);
if (angle != y_rot) {
y_rot = angle;
//emit yRotationChanged(angle);
updateGL();
}
}
void GLwindow::setZRotation(int angle)
{
qNormalizeAngle(angle);
if (angle != z_rot) {
z_rot = angle;
//emit zRotationChanged(angle);
updateGL();
}
}
/*********************
* *
* * Model view
* *
* *********************/
void GLwindow::_view_ortho() // Set Up An Ortho View
{
glMatrixMode(GL_PROJECTION); // Select Projection
glPushMatrix(); // Push The Matrix
glLoadIdentity(); // Reset The Matrix
glOrtho( 0, _width , _height, 0, -1, 1 ); // Select Ortho Mode (640x480)
glMatrixMode(GL_MODELVIEW); // Select Modelview Matrix
glPushMatrix(); // Push The Matrix
glLoadIdentity(); // Reset The Matrix
}
void GLwindow::_view_perspective() // Set Up A Perspective View
{
glMatrixMode( GL_PROJECTION ); // Select Projection
glPopMatrix(); // Pop The Matrix
glMatrixMode( GL_MODELVIEW ); // Select Modelview
glPopMatrix(); // Pop The Matrix
}
/*************************
* *
* * outil de dessin
* *
* *
* ***********************/
// Repere orthonorme
static void repereScene3D(float l)
{
glBegin (GL_LINES);
glColor3d(1.,0.,0.) ; // red axe
glVertex3f (0., 0., 0.);
glVertex3f (l, 0., 0.);
glColor3d(0.,1.,0.) ;// green axe
glVertex3f (0., 0., 0.);
glVertex3f (0., l, 0.);
glColor3d(0.,0.,1.) ;//bleu axe
glVertex3f (0., 0., 0.);
glVertex3f (0., 0., l);
glEnd ();
}
void GLwindow::_draw(){
qglColor(Qt::white);
renderText(200, 200, QString("Scene RGB"));
repereScene3D(200.0);
if(_image)
_draw_rgb();
}
/***********************************************************************************
** Project drawer
**
**
**
** *****************************************************************************/
void GLwindow::_setImg(QImage* Img){
_image = Img;
updateGL();
}
void GLwindow::_draw_Point(QRgb pixel){
// glColor4f(1.0f,1.0f,1.0f, 0.8); // Set The Alpha Value (Starts At 0.2)
qglColor(pixel);
glVertex3d(qRed(pixel)* 200 /255., qGreen(pixel) * 200 /255., qBlue(pixel) * 200 /255.);
}
void GLwindow::_draw_rgb(){
glPointSize(3.);
glBegin(GL_POINTS);
for(int i=0; i< _image->size().height();i++)
for(int j=0; j< _image->size().width();j++)
_draw_Point(_image->pixel(i,j));
glEnd();
}

70
color-space/GLwindow.h Normal file
View File

@ -0,0 +1,70 @@
/* Copyright (C) 2012 Karl Phillip Buhr <karlphillip@gmail.com>
*
* This work is licensed under the Creative Commons Attribution-ShareAlike License.
* To view a copy of this license, visit:
* https://creativecommons.org/licenses/by-sa/2.5/legalcode
*
* Or to read the human-readable summary of the license:
* https://creativecommons.org/licenses/by-sa/2.5/
*
*
* Ingress logo with glowing effect, based on Nehe lesson 36.
*/
#pragma once
#include <QGLWidget>
class GLwindow : public QGLWidget
{
Q_OBJECT
public:
explicit GLwindow(QWidget* parent = 0);
virtual ~GLwindow();
/* OpenGL initialization, viewport resizing, and painting */
void initializeGL();
void paintGL();
void resizeGL( int width, int height);
void keyPressEvent(QKeyEvent *event);
void wheelEvent(QWheelEvent *event);
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
/* Helper functions */
void setXRotation(int angle);
void setYRotation(int angle);
void setZRotation(int angle);
void _view_ortho();
void _view_perspective();
void _draw();
/*Project fonction */
void _draw_cube();
void _draw_rgb();
void _draw_hsv();
void _draw_Point(QRgb pixel);
void _setImg(QImage* Img);
private:
int _width;
int _height;
QPoint last_pos;
double x,y,z, distance;
double x_rot,y_rot,z_rot;
QImage* _image;
protected slots:
void _tick();
};

553
color-space/cvImage.cpp Normal file
View File

@ -0,0 +1,553 @@
#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,CV_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,CV_RGB2BGR);
//return res;
}
void cvImage::paintEvent(QPaintEvent* e)
{
//_onglet->children();
//get the list of tab
//QList<QWidget *> 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,CV_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,CV_RGB2HSV);
// on permute V et H pour visualisation dans Qimage
// mapage bgr d'onpencv -> permutation pour que les affiche soit corect
cv::vector<cv::Mat> 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,CV_RGB2BGR);
cv::imwrite("src.jpg",tmp);
cv::cvtColor(_img,tmp,CV_RGB2HSV);
cv::imwrite("src_HSV.jpg",tmp);
if (!_img_eq_rgb.empty()){ cv::cvtColor(_img_eq_rgb,tmp,CV_RGB2BGR); cv::imwrite("egalisation_rgb.jpg",tmp);}
if (!_img_eq_rgb1.empty()){ cv::cvtColor(_img_eq_rgb1,tmp,CV_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 cv::vector<cv::Mat>& 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(cv::vector<cv::Mat>::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 cv::vector<cv::Mat>& imSrc, cv::vector<cv::Mat>& 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;
cv::vector<cv::Mat> mv,v;//[_img.channels()];
cv::split(_img,mv);
for(cv::vector<cv::Mat>::iterator i = mv.begin(); i != mv.end();i++)
egalizhist( *i, *i);
cv::Mat merge;
cv::merge(mv,merge);
_img_eq_rgb=merge;
/*
cv::Mat hsv;
cv::cvtColor(merge,hsv,CV_RGB2HSV);
cv::vector<cv::Mat> mv_tmp;
cv::split(hsv,mv_tmp);
hsv=mv_tmp[0];
mv_tmp[0]=mv_tmp[2];
mv_tmp[2]=hsv;
cv::merge(mv_tmp,hsv);
cv::hconcat(merge,hsv,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;
cv::vector<cv::Mat> mv_src, mv_dst;
cv::split(_img,mv_src);
cv::split(_img,mv_dst);
// for(cv::vector<cv::Mat>::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;
/*
cv::Mat hsv;
cv::cvtColor(merge,hsv,CV_RGB2HSV);
cv::vector<cv::Mat> mv_tmp;
cv::split(hsv,mv_tmp);
hsv=mv_tmp[0];
mv_tmp[0]=mv_tmp[2];
mv_tmp[2]=hsv;
cv::merge(mv_tmp,hsv);
cv::hconcat(merge,hsv,merge);
*///cv::cvtColor(_imBin,imBinair,CV_GRAY2BGR);
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, CV_RGB2BGR);
cv::cvtColor(src, hsv, CV_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<float>(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);
/* cv::namedWindow( "Source", 1 );
cv::imshow( "Source", src );
cv::namedWindow( "H-S Histogram", 1 );
cv::imshow( "H-S Histogram", histImg );
*///waitKey();
}
void cvImage::_histcalc(){
if( !_img.data )
return ;
Mat src, dst;
/// Load image
src = _img;
/// Separate the image in 3 places ( B, G and R )
vector<Mat> 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<float>(i-1)) ) ,
Point( bin_w*(i), hist_h - cvRound(b_hist.at<float>(i)) ),
Scalar( 255, 0, 0), 2, 8, 0 );
line( histImage, Point( bin_w*(i-1), hist_h - cvRound(g_hist.at<float>(i-1)) ) ,
Point( bin_w*(i), hist_h - cvRound(g_hist.at<float>(i)) ),
Scalar( 0, 255, 0), 2, 8, 0 );
line( histImage, Point( bin_w*(i-1), hist_h - cvRound(r_hist.at<float>(i-1)) ) ,
Point( bin_w*(i), hist_h - cvRound(r_hist.at<float>(i)) ),
Scalar( 0, 0, 255), 2, 8, 0 );
}
/// Display
// namedWindow("calcHist Demo", CV_WINDOW_AUTOSIZE );
// imshow("calcHist Demo", histImage );
//_image = new QImage( histImage.data,histImage.size().width, histImage.size().height, histImage.step, QImage::Format_RGB888);
}

70
color-space/cvImage.h Normal file
View File

@ -0,0 +1,70 @@
#pragma once
#ifndef CVIMAGE_H
#define CVIMAGE_H
#include <QMainWindow>
#include <QMenu>
#include <QMenuBar>
#include <QImage>
#include <QKeyEvent>
#include <highgui.h>
#include <QDebug>
#include <QLabel>
#include <QPainter>
#include <QFileDialog>
#include <QApplication>
#include <QStatusBar>
#include<QMessageBox>
#include<QListWidget>
#include <cv.h>
#include"cvtab.h"
class cvImage : public QMainWindow
{
Q_OBJECT
public:
cvImage();
~cvImage();
/* fonction interne*/
void Mat2QImage(cv::Mat const& src, QImage* dest );
void QImage2Mat(QImage* const& src, cv::Mat& res);
void paintEvent(QPaintEvent* e);
void keyPressEvent(QKeyEvent* event);
void mouseMoveEvent(QMouseEvent *event);
/* fonction a rendre private/protect*/
void ajoutOnglet();
/* fonction a rendre extern (stactic)*/
void calculHist(cv::Mat& image , int* hist);
void egalizhist(cv::Mat& imSrc, cv::Mat& imDst);
void calculHist3(const cv::vector<cv::Mat>& image , int* hist);
void egalizhist3(const cv::vector<cv::Mat>& imSrc, cv::vector<cv::Mat>& imDst);
private:
QMenuBar _menu_bar;
QMenu* _menu;
QImage* _image;
cv::Mat _img;
cv::Mat _img_eq_rgb;
cv::Mat _img_eq_rgb1;
cv::Mat _imgHeq1;
cvTab _onglet;
private slots:
void _open();
void _rgbView();// visuel de source en rgb + lecteur de pixel rgb
void _hsvView();// visuel de source en hsv + lecteur de pixel hsv
void _save();
void _egalizeH();
void _egalizeH3();
void _egalizeH2();
void _histcalc();
protected:
void _close();
signals:
void closed();
};
#endif

147
color-space/cvtab.cpp Normal file
View File

@ -0,0 +1,147 @@
#include "cvtab.h"
#define MIN(X,Y) ((X) < (Y) ? : (X) : (Y))
#define MAX(a,b) \
({ __typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a > _b ? _a : _b; })
cvTab::cvTab(QWidget *parent) :
QTabWidget(parent), _image(NULL)//,_model(NULL)
{
this->setParent(parent);
_Onglet();
// connect(this , SIGNAL(currentChanged(int)),this,SLOT(_currentChangedSlot(int)));
}
void cvTab::paintEvent(QPaintEvent* e){
if(!_image)
return;
QWidget *w=NULL;
if(currentIndex()==0){
//QPainter painter(w);
//QImage I=_image->copy();
// When no image has been loaded, there's nothing to draw.
w = widget(0);
QPainter painter(this);
painter.drawImage(QPoint(10, 30), *_image);
// w->setPixmap(QPixmap::fromImage(*_image));
//resize(_image->size().height()+10,_image->size().width()+10);
//adjustSize();
}
if(currentIndex()==1){
int hR[256],hG[256],hB[256];
calculHist(_image , hR,hG,hB);
// w =widget(1);
QPainter painter(this);
painter.setWindow(-10,-10,300,300);
QLineF axe_horiz(0, 30, 0, 170);
QLineF axe_verti(-30, 0, -30, 140);
painter.setFont(QFont("Calibri", 4));
painter.drawText(-2,30,"0");
painter.drawText(-3,148+30,"255");
painter.save();
// painter.rotate(90);
painter.drawLine(axe_horiz);
//painter.restore();
painter.save();
painter.rotate(-90);
painter.drawLine(axe_verti);
painter.restore();
painter.save();
painter.rotate(-90);
QPen penR(QColor("#FF0000"), 1, Qt::DotLine, Qt::FlatCap, Qt::RoundJoin);
QPen penG(QColor("#33FF00"), 1, Qt::DotLine, Qt::FlatCap, Qt::RoundJoin);
// painter.setPen(penHLines);
QPen penB(QColor("#0000FF"), 1, Qt::DotLine, Qt::FlatCap, Qt::RoundJoin);
//painter.setPen(penR);
//recher des du max
double maxR=0,maxG=0,maxB=0;
for (int i = 0; i < 256; i++)
{
maxR= MAX(maxR,hR[i]);
maxG= MAX(maxG,hG[i]);
maxB= MAX(maxB,hB[i]);
}
for (int i = 0; i < 256; i++)
{
painter.setPen(penR);
painter.drawPoint(-i-30,hR[i]/maxR *170 );
painter.setPen(penB);
painter.drawPoint(-i-30,hB[i]/maxB *170 );
painter.setPen(penG);
painter.drawPoint(-i-30,hG[i]/maxG *170 );
}
painter.restore();
painter.save();
painter.rotate(90);
painter.save();
//resize(_image->size().height()+10,_image->size().width()+10);
//adjustSize();
}
if(currentIndex()==2){
if(_image)
Histogramme_3D._setImg(_image);
}
show();
QWidget::paintEvent(e);
}
void cvTab::calculHist(QImage* image , int* histR,int*histG,int* histB)
{
int i;
if(image->allGray())
return;
/* initialisation de l'histogramme a 0*/
for(i = 0; i < 256;i++){
histR[i]=0;
histG[i]=0;
histB[i]=0;
}
/* calcule des valeur de l'histogramme */
for(int x = 0; x < image->width(); x++)
for(int y=0; y< image->height();y++){
histR[qRed(image->pixel(x,y))]++;
histG[qGreen(image->pixel(x,y))]++;
histB[qBlue(image->pixel(x,y))]++;
}
}
void cvTab::setImg(QImage* Img){
if(Img)
_image=Img;
}
//Slot that is called when Tab selection changes
void cvTab::_currentChangedSlot(int index)
{
if(currentIndex()==index)
return;
currentWidget()->hide();
setCurrentIndex(index);
currentWidget()->show();
// update();
}
void cvTab::_Onglet()
{
addTab(&Visuel,tr("Visuel"));
addTab(&Histograme_2D,tr("Histograme 2D"));
addTab(&Histogramme_3D,tr("Histogramme 3D"));
//setCurrentWidget(ajout);
connect(this,SIGNAL(currentChanged(int)), this,SLOT(_currentChangedSlot(int))) ;
}

41
color-space/cvtab.h Normal file
View File

@ -0,0 +1,41 @@
#ifndef CVTAB_H
#define CVTAB_H
#include <QTabWidget>
#include <QPainter>
#include<QLabel>
#include "GLwindow.h"
class cvTab : public QTabWidget
{
Q_OBJECT
public:
explicit cvTab(QWidget *parent = 0);
// void keyPressEvent(QKeyEvent* event);
// void mouseMoveEvent(QMouseEvent *event);
void paintEvent(QPaintEvent* e);
void _Onglet();
void setImg(QImage* Img);
// void setModel(QGLWidget * Model);
static void calculHist(QImage* image , int* histR,int*histG,int* histB);
signals:
private:
QLabel Visuel;
QLabel Histograme_2D ;
GLwindow Histogramme_3D ;
QImage* _image;
// QGLWidget *_model;
public slots:
//Slot that is called when Tab selection changes
void _currentChangedSlot(int index);
};
#endif // CVTAB_H

26
color-space/main.cpp Normal file
View File

@ -0,0 +1,26 @@
/* Copyright (C) 2013 Karl Phillip Buhr <karlphillip@gmail.com>
*
* This work is licensed under the Creative Commons Attribution-ShareAlike License.
* To view a copy of this license, visit:
* https://creativecommons.org/licenses/by-sa/2.5/legalcode
*
* Or to read the human-readable summary of the license:
* https://creativecommons.org/licenses/by-sa/2.5/
*/
#include "cvImage.h"
#include <QApplication>
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
cvImage win;
win.show();
QObject::connect(&win, SIGNAL(closed()),
&app, SLOT(quit()) );
return app.exec();
}

73
color-space/prj.pro Normal file
View File

@ -0,0 +1,73 @@
TEMPLATE = app
QT += core gui opengl
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
contains(QT_VERSION, ^5\\.[0-8]\\..*) {
message("* Using Qt $${QT_VERSION}.")
QT += widgets
# On my system I have to specify g++ as compiler else it will use clang++ by default
#QMAKE_CXX=g++
#QMAKE_CC=gcc
}
SOURCES += \
main.cpp \
cvImage.cpp \
cvtab.cpp \
GLwindow.cpp
HEADERS += \
cvImage.h \
cvtab.h \
GLwindow.h
## OpenCV settings for Unix/Linux
unix:!mac {
message("* Using settings for Unix/Linux.")
INCLUDEPATH += /usr/local/include/opencv
LIBS += -L/usr/local/lib/ \
-lopencv_core \
-lopencv_highgui \
-lopencv_imgproc \
-lGLU
}
## OpenCV settings for Mac OS X
macx {
message("* Using settings for Mac OS X.")
INCLUDEPATH += /usr/local/include/opencv
LIBS += -L/usr/local/lib/ \
-lopencv_core \
-lopencv_highgui \
-lopencv_imgproc
}
## OpenCV settings for Windows and OpenCV 2.4.2
win32 {
message("* Using settings for Windows.")
INCLUDEPATH += "C:\\opencv\\build\\include" \
"C:\\opencv\\build\\include\\opencv" \
"C:\\opencv\\build\\include\\opencv2"
CONFIG(debug, debug | release) {
LIBS += -L"C:\\opencv\\build\\x86\\vc10\\lib" \
-lopencv_core248d \
-lopencv_highgui248d \
-lopencv_imgproc248d
}
CONFIG(release, debug | release) {
LIBS += -L"C:\\opencv\\build\\x86\\vc10\\lib" \
-lopencv_core248 \
-lopencv_highgui248 \
-lopencv_imgproc248
}
}
# Runs this app automatically after the building has succeeded
#QMAKE_POST_LINK=./$$TARGET