add color space project
BIN
assets/images/4N.png
Normal file
|
After Width: | Height: | Size: 5.6 KiB |
BIN
assets/images/4NI.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
BIN
assets/images/IM2.png
Normal file
|
After Width: | Height: | Size: 467 KiB |
5916
assets/images/Lenna.pgm
Normal file
BIN
assets/images/Lenna.png
Normal file
|
After Width: | Height: | Size: 463 KiB |
BIN
assets/images/LennaM1.png
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
BIN
assets/images/LennaM2.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
assets/images/lena_b.jpg
Normal file
|
After Width: | Height: | Size: 35 KiB |
BIN
assets/images/sk.jpg
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
assets/images/sk.pgm
Normal file
BIN
assets/images/sk.png
Normal file
|
After Width: | Height: | Size: 49 KiB |
BIN
assets/images/skg.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
assets/images/src.jpg
Normal file
|
After Width: | Height: | Size: 105 KiB |
BIN
assets/images/src_HSV.jpg
Normal file
|
After Width: | Height: | Size: 147 KiB |
185
color-space/AnaglypheWebcam_base.cpp
Normal 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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||||