Initial commit

This commit is contained in:
Phyks 2013-07-28 15:24:49 +02:00
commit 80a0b2dd97
39 changed files with 1875 additions and 0 deletions

BIN
29.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
29.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 534 B

BIN
29_grey.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 B

BIN
30.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 534 B

BIN
30_small.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 523 B

BIN
31.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 541 B

BIN
Algorithm.pdf Normal file

Binary file not shown.

BIN
IMG_0114b.JPG Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 KiB

BIN
IMG_0114s.JPG Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 KiB

BIN
IMG_0114s.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

BIN
IMG_0115b.JPG Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 335 KiB

BIN
IMG_0115s.JPG Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 KiB

BIN
Left.JPG Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 MiB

BIN
Left2.JPG Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 359 KiB

View File

@ -0,0 +1,3 @@
D = 36mm
f = 38mm
deltaX = 8cm

30
RGB2grey.c Normal file
View File

@ -0,0 +1,30 @@
unsigned char** RGB2grey(unsigned char*** image, int width, int height)
{
unsigned char** grey;
int x,y;
if((grey = malloc(sizeof(*grey) * height)) == NULL)
{
perror("malloc:");
return NULL;
}
for(y = 0; y <= height; y++)
{
if((grey[y] = malloc(sizeof(**grey) * width)) == NULL)
{
perror("malloc:");
return NULL;
}
}
for(y = 0; y <= height; y++)
{
for(x = 0; x <= width; x++)
{
grey[y][x] = (unsigned char) (0.2125*image[y][x][0] + 0.7154*image[y][x][1] + 0.0721*image[y][x][2]);
//Formula found here : https://fr.wikipedia.org/wiki/Niveau_de_gris
}
}
return grey;
}

BIN
Rapport/IMG_0114s.JPG Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 KiB

BIN
Rapport/IMG_0115s.JPG Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 KiB

BIN
Rapport/Left.JPG Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 MiB

BIN
Rapport/Right.JPG Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

27
Rapport/biblio.bib Normal file
View File

@ -0,0 +1,27 @@
@misc{article,
title = {Distance Estimation Algorithm for Stereo Pair Images},
author = {TjandranegaraB, Edwin},
howpublished="\url{http://docs.lib.purdue.edu/ecetr/64/}",
year = {article daté de 2005, dernière consultation en décembre 2012},
}
@misc{article2,
title = {Distance measuring based on stereoscopic pictures},
author = {Mrovlje1, Jernej and Vranči, Damir},
howpublished="\url{http://photon07.pd.infn.it:5210/users/dazzi/Thesis_doctorate/Info/Chapter_6/Stereoscopy_(Mrovlje).pdf}",
year = {article daté de 2008, dernière consultation en décembre 2012},
}
@misc{templateMatching,
title = {OpenCV wiki page about template matching},
author = {},
howpublished="\url{http://docs.opencv.org/doc/tutorials/imgproc/histograms/template_matching/template_matching.html}",
year = {dernière consultation en janvier 2013},
}
@misc{phaseCorrelation,
title = {Wikipedia page about phase correlation},
author = {},
howpublished="\url{http://en.wikipedia.org/wiki/Phase_correlation}",
year = {dernière consultation en janvier 2013},
}

42
Rapport/rapport.aux Normal file
View File

@ -0,0 +1,42 @@
\relax
\providecommand\hyper@newdestlabel[2]{}
\catcode`:\active
\catcode`;\active
\catcode`!\active
\catcode`?\active
\providecommand\HyperFirstAtBeginDocument{\AtBeginDocument}
\HyperFirstAtBeginDocument{\ifx\hyper@anchor\@undefined
\global\let\oldcontentsline\contentsline
\gdef\contentsline#1#2#3#4{\oldcontentsline{#1}{#2}{#3}}
\global\let\oldnewlabel\newlabel
\gdef\newlabel#1#2{\newlabelxx{#1}#2}
\gdef\newlabelxx#1#2#3#4#5#6{\oldnewlabel{#1}{{#2}{#3}}}
\AtEndDocument{\ifx\hyper@anchor\@undefined
\let\contentsline\oldcontentsline
\let\newlabel\oldnewlabel
\fi}
\fi}
\global\let\hyper@last\relax
\gdef\HyperFirstAtBeginDocument#1{#1}
\providecommand\HyField@AuxAddToFields[1]{}
\providecommand\HyField@AuxAddToCoFields[2]{}
\select@language{french}
\@writefile{toc}{\select@language{french}}
\@writefile{lof}{\select@language{french}}
\@writefile{lot}{\select@language{french}}
\@writefile{toc}{\contentsline {section}{\numberline {1}Objectif}{1}{section.1}}
\@writefile{toc}{\contentsline {section}{\numberline {2}M\IeC {\'e}thode choisie}{1}{section.2}}
\@writefile{toc}{\contentsline {subsection}{\numberline {2.1}Distance euclidienne dans l'espace RGB}{1}{subsection.2.1}}
\@writefile{toc}{\contentsline {subsection}{\numberline {2.2}Cross-correlation \emph {via} FFT}{1}{subsection.2.2}}
\citation{article}
\citation{article2}
\citation{templateMatching}
\citation{phaseCorrelation}
\bibstyle{plain-fr}
\bibdata{biblio}
\bibcite{templateMatching}{1}
\@writefile{toc}{\contentsline {section}{\numberline {3}R\IeC {\'e}sultats}{2}{section.3}}
\@writefile{toc}{\contentsline {section}{\numberline {4}Optimisations possibles}{2}{section.4}}
\bibcite{phaseCorrelation}{2}
\bibcite{article2}{3}
\bibcite{article}{4}

30
Rapport/rapport.bbl Normal file
View File

@ -0,0 +1,30 @@
\begin{thebibliography}{1}
\expandafter\ifx\csname fonteauteurs\endcsname\relax
\def\fonteauteurs{\scshape}\fi
\bibitem{templateMatching}
Opencv wiki page about template matching.
\newblock
\url{http://docs.opencv.org/doc/tutorials/imgproc/histograms/template_matching/template_matching.html},
dernière consultation en janvier 2013.
\bibitem{phaseCorrelation}
Wikipedia page about phase correlation.
\newblock \url{http://en.wikipedia.org/wiki/Phase_correlation}, dernière
consultation en janvier 2013.
\bibitem{article2}
Jernej \bgroup\fonteauteurs\bgroup Mrovlje1\egroup\egroup{} et Damir
\bgroup\fonteauteurs\bgroup Vranči\egroup\egroup{} :
\newblock Distance measuring based on stereoscopic pictures.
\newblock
\url{http://photon07.pd.infn.it:5210/users/dazzi/Thesis_doctorate/Info/Chapter_6/Stereoscopy_(Mrovlje).pdf},
article daté de 2008, dernière consultation en décembre 2012.
\bibitem{article}
Edwin \bgroup\fonteauteurs\bgroup TjandranegaraB\egroup\egroup{} :
\newblock Distance estimation algorithm for stereo pair images.
\newblock \url{http://docs.lib.purdue.edu/ecetr/64/}, article daté de 2005,
dernière consultation en décembre 2012.
\end{thebibliography}

49
Rapport/rapport.blg Normal file
View File

@ -0,0 +1,49 @@
This is BibTeX, Version 0.99d (TeX Live 2012/Arch Linux)
Capacity: max_strings=35307, hash_size=35307, hash_prime=30011
The top-level auxiliary file: rapport.aux
The style file: plain-fr.bst
Database file #1: biblio.bib
Warning--to sort, need author or key in templateMatching
Warning--to sort, need author or key in phaseCorrelation
You've used 4 entries,
2238 wiz_defined-function locations,
554 strings with 5349 characters,
and the built_in function-call counts, 936 in all, are:
= -- 99
> -- 21
< -- 0
+ -- 10
- -- 6
* -- 34
:= -- 174
add.period$ -- 8
call.type$ -- 4
change.case$ -- 15
chr.to.int$ -- 0
cite$ -- 6
duplicate$ -- 28
empty$ -- 93
format.name$ -- 6
if$ -- 213
int.to.chr$ -- 0
int.to.str$ -- 4
missing$ -- 0
newline$ -- 23
num.names$ -- 4
pop$ -- 33
preamble$ -- 1
purify$ -- 11
quote$ -- 0
skip$ -- 28
stack$ -- 0
substring$ -- 44
swap$ -- 4
text.length$ -- 0
text.prefix$ -- 0
top$ -- 0
type$ -- 16
warning$ -- 2
while$ -- 4
width$ -- 5
write$ -- 40
(There were 2 warnings)

6
Rapport/rapport.out Normal file
View File

@ -0,0 +1,6 @@
\BOOKMARK [1][-]{section.1}{Objectif}{}% 1
\BOOKMARK [1][-]{section.2}{M\351thode choisie}{}% 2
\BOOKMARK [2][-]{subsection.2.1}{Distance euclidienne dans l'espace RGB}{section.2}% 3
\BOOKMARK [2][-]{subsection.2.2}{Cross-correlation via FFT}{section.2}% 4
\BOOKMARK [1][-]{section.3}{R\351sultats}{}% 5
\BOOKMARK [1][-]{section.4}{Optimisations possibles}{}% 6

BIN
Rapport/rapport.pdf Normal file

Binary file not shown.

101
Rapport/rapport.tex Normal file
View File

@ -0,0 +1,101 @@
\documentclass[10pt,a4paper]{article}
\usepackage{ifpdf}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[francais]{babel}
\usepackage{lmodern}
\usepackage{graphicx}
\usepackage{amsmath}
\usepackage{amsfonts}
\usepackage{amssymb}
\usepackage{enumitem}
\usepackage[margin=1.5cm]{geometry}
\usepackage{hyperref}
\usepackage{url}
\title{Projet de Physique Numérique : Mesure de distances par stéréoscopie}
\author{Lucas Verney}
\date{2012/2013}
\ifpdf
\pdfinfo {
/Author (Lucas Verney)
/Title (Projet de Physique Numérique : Mesure de distances par stéréoscopie)
}
\fi
\begin{document}
\maketitle
\section{Objectif}
Le but de ce projet était de déterminer des distances séparant un observateur d'un objet à partir de deux photos de cet objet prises en déplaçant horizontalement l'appareil entre les prises de vue. En utilisant la stéréoscopie, on peut en effet déterminer la distance nous séparant de l'objet, tout comme notre cerveau est capable d'estimer les distances nous séparant des objets à partir des ``images'' captées par nos yeux.
\bigskip
\underline{\emph{Exemple :}}
\medskip
\begin{center}
\begin{tabular}{cc}
\includegraphics[scale=0.25]{IMG_0114s.JPG} & \includegraphics[scale=0.25]{IMG_0115s.JPG} \\
\emph{Image de gauche} & \emph{Image de droite} \\
\end{tabular}
\end{center}
\section{Méthode choisie}
Il faut, dans un premier temps, déterminer le déplacement en pixels de l'objet entre les deux images. Dans un deuxième temps, il faut traduire ce déplacement en distance réelle nous séparant de l'objet.
\subsection{Distance euclidienne dans l'espace RGB}
Pour déterminer le déplacement en pixels, on considère une grille de $n\times n$ pixels, qu'on superpose à notre image de gauche (par défaut, $n = 50$ dans le programme). Pour chaque carrés de $n\times n$ pixels, on cherche le carré qui lui correspond le plus dans l'image de droite. Pour ce faire, on va parcourir chaque pixel de l'image de droite et comparer le carré de l'image de gauche et le carré dont le coin supérieur gauche est le pixel courant dans l'image de droite.
Les images étant chargées en couleur (RGB), on est dans un espace à trois dimensions (R, G et B) dont les coordonnées des pixels sont entre $0$ et $255$ (profondeur de couleur de 8 bits). On peut donc estimer la ``distance'' séparant les deux carrés par la moyenne sur le carré des distances pixel à pixel où la distance pixel à pixel est la distance euclidienne standard ($=\sqrt{(R_2 - R_1)^2 + (G_2 - G_1)^2 + (B_2 - B_1)^2}$).
\subsection{Cross-correlation \emph{via} FFT}
Une autre possibilité est d'utiliser la cross-correlation (ou la phase correlation) afin de déterminer la position de notre objet.
On commence par charger les images en niveaux de gris et on récupère le carré qu'on considère dans une nouvelle image, de la même taille que l'image de droite. On complète cette image par du noir (des 0) qui n'interviendront donc pas dans la transformation de Fourier.
On effectue ensuite les transformations de fourier de chaque image et on multiplie le spectre de l'image de droite par le conjugué du spectre du carré dont on cherche la position. On normalise ensuite la transformation de Fourier (en divisant chaque la valeur de chaque point par son module) et on repasse en espace réel (\emph{via} une transformation de Fourier inverse.
On cherche ensuite la valeur de la plus grande amplitude sur cette image, qui correspond à la position du carré qu'on cherche.
\bigskip
Une fois cette distance déterminée, on peut en déduire la distance nous séparant de l'objet en utilisant les formules explicitées dans \cite{article}. Connaissant les caractéristiques de l'appareil, il est facile de traduire le déplacement en pixels précédent en distance réelle.
\section{Résultats}
Le programme obtenu a été testée sur le jeu d'images suivant (les tests ont été effectués en considérant le coin inférieur gauche du carré noir) :
\begin{center}
\begin{tabular}{cc}
\includegraphics[scale=0.05]{Left.JPG} & \includegraphics[scale=0.05]{Right.JPG} \\
\emph{Image de gauche} & \emph{Image de droite} \\
\end{tabular}
\end{center}
Le programme décrit précédemment permet de déterminer très précisément le déplacement du coin inférieur gauche et on ne peut obtenir une meilleure précision manuellement. Ce résultat a été obtenu en une vingtaine de secondes en utilisant les $4$ c{\oe}urs du processeur, ce qui est relativement long. En effet, pour parcourir toute l'image avec la méthode précédente et des carrés de $50$ pixels de large, il faudrait environ $30h$.
Après conversion du déplacement en pixels en distance réelle, on trouve une distance réelle de $15cm$ contre $35cm$ en réalité (en utilisant des caractéristiques ``moyennes'' pour l'appareil photo). Cependant, le déplacement étant convenablement détecté, cet écart provient d'une méconnaissance des caractéristiques précises de l'appareil photo utilisé (notamment sa distance focale).
En conclusion, cette technique nous permet de déterminer des distances très précisément mais est très coûteuse en ressources et il est difficilement envisageable de couvrir une photo entière avec cette méthode.
La technique utilisant la transformée de fourier rapide est nettement plus rapide (une vingtaine de secondes par image) et donne des résultats légèrement moins précis mais largement comparables.
\medskip
\emph{Remarque :} Il faut également noter qu'on ne détermine pas la distance nous séparant d'un objet (ou d'un point) précis mais une moyenne de cette distance sur un carré de $n$ pixels de large. Il faut donc choisir la taille de ce carré petite devant l'échelle caractéristique de variation des distances (liée à la taille transversale des objets).
\emph{Remarque :} On peut également utiliser un algorithme de détection de contours (type filtre de Sobel qui calcule le ``gradient'' de l'image) pour travailler sur une image en niveau de gris et déterminer les distances nous séparant des contours des objets, ceci afin d'obtenir une meilleure précision sur des images chargées.
\section{Optimisations possibles}
Comme on l'a vu précédemment, la méthode employée est très coûteuse en ressources. On peut envisager diverses optimisations :
\begin{itemize}
\item On peut envisager d'appliquer un filtre de détection de contours (type filtre de Sobel) avant de travailler sur l'image. On peut alors se restreindre aux zones d'intérêt, c'est-à-dire aux contours représentés par des pixels blancs.
\item Pour accélérer le calcul des distances, on peut envisager de paralléliser au maximum les opérations. Dans le code présenté, on utilise jusqu'à $4$ c{\oe}urs du processeur mais l'utilisation de la puce graphique pourrait accélérer le calcul, celle-ci travaillant naturellement avec des calculs parallèles.
\item Jusqu'ici, on n'a envisagé qu'un déplacement horizontal (ou vertical en travaillant sur une image retournée). On pourrait envisager le cas d'un déplacement quelconque dans l'espace (translation) en adaptant les formules.
\end{itemize}
\nocite{article2}
\nocite{templateMatching}
\nocite{phaseCorrelation}
\bibliographystyle{plain-fr}
\bibliography{biblio}
\end{document}

BIN
Right.JPG Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

BIN
Right2.JPG Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 311 KiB

BIN
Stereoscopy_(Mrovlje).pdf Normal file

Binary file not shown.

BIN
Test.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

BIN
TestL.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

BIN
TestR.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

BIN
bmp Executable file

Binary file not shown.

165
bmp.c Normal file
View File

@ -0,0 +1,165 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//Note : BMP files are written from left to right but from bottom to top !
struct file_header
{
char signature[3];
int size;
int reserved;
int offset;
};
struct img_header
{
int headerSize;
int width;
int height;
int planes;
int depth;
int compress;
int imgSize;
int resX;
int resY;
int colors;
int importantColors;
};
struct file_header get_file_header(FILE* file)
{
struct file_header fh={"", 0, 0, 0};
fread(&fh.signature, 2, 1, file);
fread(&fh.size, 4, 1, file);
fread(&fh.reserved, 4, 1, file);
fread(&fh.offset, 4, 1, file);
return fh;
}
struct img_header get_img_header(FILE* file)
{
struct img_header ih={0,0,0,0,0,0,0,0,0,0,0};
fread(&ih.headerSize, 4, 1, file);
fread(&ih.width, 4, 1, file);
fread(&ih.height, 4, 1, file);
fread(&ih.planes, 2, 1, file);
fread(&ih.depth, 2, 1, file);
fread(&ih.compress, 4, 1, file);
fread(&ih.imgSize, 4, 1, file);
fread(&ih.resX, 4, 1, file);
fread(&ih.resY, 4, 1, file);
fread(&ih.colors, 4, 1, file);
fread(&ih.importantColors, 4, 1, file);
return ih;
}
int main (int argc, char* argv[])
{
if(argc < 2)
{
fprintf(stderr, "Error : you must specify a bmp image to open.\n");
return EXIT_FAILURE;
}
//All the variables we'll use
FILE *file;
const char* filename;
filename = argv[1];
struct file_header fileHeader;
struct img_header imageHeader;
int x, y, yImage;
unsigned char ***image;
file = fopen(filename, "rb"); //First, open the file in binary mode
if(file == NULL)
{
fprintf(stderr, "Error : can't open the bmp image.\n");
return EXIT_FAILURE;
}
fileHeader = get_file_header(file); //Get the file header and check it is a bmp file
if(strcmp(fileHeader.signature, "BM") != 0 && strcmp(fileHeader.signature, "BA") != 0 && strcmp(fileHeader.signature, "CI") != 0 && strcmp(fileHeader.signature, "CP") != 0 && strcmp(fileHeader.signature, "IC") != 0 && strcmp(fileHeader.signature, "PT") != 0)
{
fprintf(stderr, "Error : This file is not a valid BMP image.\n");
return EXIT_FAILURE;
}
imageHeader = get_img_header(file); //Get the image header
if(imageHeader.compress != 0)
{
fprintf(stderr, "Error : The BMP file is compressed. This program can't open such files.\n");
return EXIT_FAILURE;
}
if(imageHeader.depth != 24) //If it is not a "true-color" RGB bmp file (ie 24 bits per pixel)
{
fprintf(stderr, "Error : This BMP is not a standard true-color BMP file. It may be a 256 colors BMP file for example.\n");
return EXIT_FAILURE;
}
//Allocation dynamique pour l'image
if((image = malloc(sizeof(*image) * imageHeader.height)) == NULL)
{
perror("malloc:");
return EXIT_FAILURE;
}
for(y = 0; y <= imageHeader.height; y++)
{
if((image[y] = malloc(sizeof(**image) * imageHeader.width)) == NULL)
{
perror("malloc:");
return EXIT_FAILURE;
}
}
for(y = 0; y <= imageHeader.height; y++)
{
for(x = 0; x <= imageHeader.width; x++)
{
if((image[y][x] = malloc(sizeof(***image) * 3)) == NULL) //image[y][x][R,G,B]
{
perror("malloc:");
return EXIT_FAILURE;
}
image[y][x][0] = 0;
image[y][x][1] = 0;
image[y][x][2] = 0;
}
}
fseek(file, fileHeader.offset, SEEK_SET); //We don't get all the possible headers, so go to the start of the image informations
for(y = 0; y <= imageHeader.height; y++) //Get all the values for all the pixels in the image
{
for(x = 0; x <= imageHeader.width; x++)
{
yImage = imageHeader.height - y; //Due to the fact that BMP file are written from bottom to top
fread(&image[yImage][x][2], 1, 1, file);
fread(&image[yImage][x][1], 1, 1, file);
fread(&image[yImage][x][0], 1, 1, file);
}
}
printf("Output is : (Coordinates of the pixel) : value of each channel");
for(y = 0; y <= imageHeader.height; y++)
{
for(x = 0; x <= imageHeader.width; x++)
{
printf("(%d,%d) : R = %d,G = %d,B = %d\n", x, y, image[y][x][0], image[y][x][1], image[y][x][2]);
}
}
free(image);
fclose(file);
return EXIT_SUCCESS;
}

10
makefile Normal file
View File

@ -0,0 +1,10 @@
all: stereo bmp
stereo : stereo.o
gcc stereo.o -o stereo `pkg-config opencv --libs` -lm -lpthread -lfftw3 -lfftw3_threads
stereo.o : stereo.c
gcc -c stereo.c -Wall `pkg-config opencv --cflags` -lm -lpthread -lfftw3 -lfftw3_threads
bmp : bmp.c
gcc -o bmp bmp.c

75
sobel.c Normal file
View File

@ -0,0 +1,75 @@
unsigned char** Sobel(unsigned char*** image, int width, int height)
//cf. http://docs.opencv.org/doc/tutorials/imgproc/imgtrans/sobel_derivatives/sobel_derivatives.html#sobel-derivatives and https://fr.wikipedia.org/wiki/Algorithme_de_Sobel
{
unsigned char** sobel;
int x,y,i;
unsigned char tempx, tempy;
if((sobel = malloc(sizeof(*sobel) * height)) == NULL)
{
perror("malloc:");
return NULL;
}
for(y = 0; y <= height; y++)
{
if((sobel[y] = malloc(sizeof(**sobel) * width)) == NULL)
{
perror("malloc:");
return NULL;
}
for(x = 0; x <= width; x++)
{
sobel[y][x] = 0;
}
}
for(y = 1; y < height; y++)
{
for(x = 1; x < width; x++)
{
tempx = -image[y-1][x-1]+image[y-1][x+1]-2*image[y][x-1]+2*image[y][x+1]-image[y+1][x-1]+image[y+1][x+1];
tempy = -image[y-1][x-1]-2*image[y-1][x]-image[y-1][x+1]+image[y+1][x-1]+2*image[y+1][x]+image[y+1][x+1];
sobel[y][x] = (int) floor(sqrt(tempx^2 + tempy^2));
}
}
return sobel;
}
unsigned char*** add2images(unsigned char*** image1, unsigned char*** image2, int width, int height, int nChannels)
{
unsigned char*** sum;
int x,y,i;
if((sum = malloc(sizeof(*sum) * height)) == NULL)
{
perror("malloc:");
return NULL;
}
for(y = 0; y <= height; y++)
{
if((sum[y] = malloc(sizeof(**sum) * width)) == NULL)
{
perror("malloc:");
return NULL;
}
}
for(y = 0; y <= height; y++)
{
for(x = 0; x <= width; x++)
{
if((sum[y][x] = malloc(sizeof(***sum) * nChannels)) == NULL) //sum[y][x][R,G,B]
{
perror("malloc:");
return NULL;
}
for(i = 0; i < nChannels; i++)
{
sum[y][x] = (unsigned char) ((image1[y][x][i] + image2[y][x][i])/2);
}
}
}
return sum;
}

BIN
stereo Executable file

Binary file not shown.

1337
stereo.c Normal file

File diff suppressed because it is too large Load Diff