Programación Ansi - C
21/7/11
19/7/11
Visión Computacional y Procesamiento de imágenes
Comenzaré a publicar todo acerca de los temas en los que estaré trabajando este verano científico, a continuación explico el concepto y aplicaciones de la visión computacional y el procesamiento de imágenes.
Para empezar ¿Qué es visión ?
Algunos autores la definen como la capacidad que tiene el ojo humano para percibir nuestro entorno para despues ser interpretada por el cerebro.
Cito algunas definiciones :
- Visión es saber que hay y dónde mediante la vista. (Aristóteles)
- Visión es un proceso que produce a partir de imágenes del mundo exterior una descripción que es util al observador y que no tiene información irrelevante. (Marr)
Entonces la visión computacional trata de emular esa capacidad mediante herramientas computacionales que prodían ser camaras que captan la información del exterior y su posición espacial para despues reconocerlos e interpretarlos.
Por otro lado un área muy ligada a la visión computacional es el procesamiento de imágenes , pues ambos campos tienen mucho en común pero el objetivo final es otro, pues el procesamiento de imágenes esta orientado a MEJORAR la calidad de las imágenes para su posterior interpetración por una persona y la visión computacional trata de obtener atributos y descripciones para tratar de interpretar la imagen automaticamente.
Entonces concluimos que visión computacional va orientado a tratar de interpretar la imagén que percibe por sí misma y el procesamiento de imágenes va destinado a mejorar la imagen para su posterior interpretación por una persona.
Aplicaciones:
*Visión Computacional
- Reconocimiento de objetos y formas en una imagen.
- Analizar objetos para determinar su calidad.
- Descomposición de objetos en sus partes.
*Procesamiento de imágenes
- Remover defectos de una imagen.
- Aumentar carácteristicas de una imagen (color ,contraste, estrutura).
- Agregar colores y convertir imágenes monocromáticas.
Referencias Bibliográficas.
Libro Procesamiento de Imágenes y Visión Computacional, Enrique Sucar y Giovani Gómez.
Verano Científico
Este blog fue creado con el objetivo de subir tareas y avances de la materia "Lenguaje ANSI-C" que impartió la Dra. Schaeffer durante el verano en la Facultad de Ingeniería Mecánica y Eléctrica(FIME) de la Universidad Autónoma de Nuevo León (UANL) a la cuál tuve la oportunidad de entrar como oyente. Todo esto debido a que estoy realizando la estadía del Verano Científico en la UANL que tiene como meta acercar y motivar a alumnos de nivel licenciatura a estudiar un posgrado . Una de las actividades principales es la realización de una investigación bajo la supervisión de un investigador, en mi caso estaré supervisado por él M.C. David J. Ríos y asu vez también por la Dra. Elisa Schaeffer.
Entonces de ahora en adelante cambiará el enfoque de este blog pues ahora estaré subiendo entradas acerca de la investigación que realizaré. Saludos y buenas noches.
14/7/11
Videos sobre Punteros
Les comparto este video que tomé de youtube donde explica lo más básico sobre punteros, como se declara, que imprime puntero,&puntero y *puntero, aunque es para el lenguaje c++ ,ansi c es muy parecido , es de gran ayuda para nosotros que apenas ingresamos al mundo de la programación. Agradecimientos al autor del video .Espero les sea de utilidad.
Arboles..
Para realizar la operación de borrado , se tienen que tener en consideracion varios cosas:
Borrar un nodo sin hijos ó nodo hoja: Simplemente se borra y se establece a nulo el apuntador
de su padre.
Borrar un nodo con un subárbol hijo: se borra el nodo y se asigna su subárbol hijo como subárbol de su padre.
Borrar un nodo con dos subárboles hijo: la solución está en reemplazar el valor del nodo por el
de su predecesor o por el de su sucesor en inorden y posteriormente borrar este nodo. Su predecesor en
inorden será el nodo más a la derecha de su subárbol izquierdo (mayor nodo del subarbol izquierdo), y su sucesor el nodo más a la izquierda de
su subárbol derecho (menor nodo del subarbol derecho).Aunque en realidad aún no he podido implementarlo =(.. pues el codigo no hace lo que debería.
Toda esta información la encontré en wikipedia. http://es.wikipedia.org/wiki/%C3%81rbol_binario_de_b%C3%BAsqueda
Borrar un nodo sin hijos ó nodo hoja: Simplemente se borra y se establece a nulo el apuntador
de su padre.
Borrar un nodo con un subárbol hijo: se borra el nodo y se asigna su subárbol hijo como subárbol de su padre.
Borrar un nodo con dos subárboles hijo: la solución está en reemplazar el valor del nodo por el
de su predecesor o por el de su sucesor en inorden y posteriormente borrar este nodo. Su predecesor en
inorden será el nodo más a la derecha de su subárbol izquierdo (mayor nodo del subarbol izquierdo), y su sucesor el nodo más a la izquierda de
su subárbol derecho (menor nodo del subarbol derecho).Aunque en realidad aún no he podido implementarlo =(.. pues el codigo no hace lo que debería.
Toda esta información la encontré en wikipedia. http://es.wikipedia.org/wiki/%C3%81rbol_binario_de_b%C3%BAsqueda
#include <stdio.h> #include <stdlib.h> #include <assert.h> #include "bool.h" #define DEBUG 1 // NOTA: faltan implementar las rotaciones // dobles; por ahora no balancea bien // un nodo de ruteo no cuenta duplicados #define NO_VALIDO -1 int next = 0; struct nodo_de_arbol { char dato; int altura; int contador; int id; struct nodo_de_arbol* padre; struct nodo_de_arbol* izq; // hijo struct nodo_de_arbol* der; // otro hijo }; typedef struct nodo_de_arbol nodo; void borra(nodo* n) { if (n == NULL) { return; } else { borra(n->izq); borra(n->der); free(n); } return; } void muestra(nodo* n) { if (n == NULL) { return; // caso base de recursion } else { muestra(n->izq); if (n->izq != NULL && n->der != NULL) { printf("[%c, %d <%d / %d, %d>] ", n->dato, n->altura, n->id, n->izq->id, n->der->id); } else { printf("(%c, %d <%d> #%d) ", n->dato, n->altura, n->id, n->contador); } if (n->izq == NULL && n->der == NULL) { printf("%c[%d] ", n->dato, n->contador); } muestra(n->der); } return; } void elimina(nodo* n,nodo** raiz){
nodo-> NULL;
} void balancea(nodo* n, nodo** raiz) { int ai, ad, max, min, aalt, balt; nodo* t = NULL; nodo* u = NULL; nodo* v = NULL; nodo* a = NULL; nodo* b = NULL; nodo* p = NULL; nodo* x1 = NULL; nodo* x2 = NULL; if (n == NULL) { printf("Ya topamos con la raiz.\n"); return; } if (n->izq == NULL || n->der == NULL) { printf("No se puede sin hijos.\n"); return; } t = n; // nodo actual assert(t != NULL); printf("Checando balance en %c (alt. %d).\n", t->dato, t->altura); u = n->izq; // hijo izquierdo assert(u != NULL); v = n->der; // hijo derecho assert(v != NULL); ai = u->altura; ad = v->altura; printf("Hijos %c (alt. %d) y %c (alt. %d).\n", u->dato, ai, v->dato, ad); max = (ai > ad) ? ai : ad; min = (ai > ad) ? ad : ai; if (max + 1 != t->altura) { t->altura = max + 1; // actualizar altura } if (max - min > 1) { // balancear p = t->padre; // padre del actual printf("%c a altura %d requiere balanceo.\n", t->dato, t->altura); printf("Entrando tenemos:\n"); if (p != NULL) { printf("p = %d, ", p->id); } else { printf("p = NULL, "); } printf("t = %d, \n", t->id); printf("u = %d, v = %d, \n", u->id, v->id); if (ai <= ad - 2) { // si hay demasiada altura a la der // => voltear "peso" hacia la izq. a = v->izq; b = v->der; assert(a != NULL); assert(b != NULL); aalt = a->altura; balt = b->altura; printf("a = %d, b = %d, \n", a->id, b->id); if (aalt <= balt) { // rotacion simple izq printf("Simple izquierda.\n"); if (p != NULL) { // v debe reemplazar a t como hijo if (p->izq == t) { p->izq = v; } else { // era derecho p->der = v; } } else { // v es ahora raiz *raiz = v; } // el padre de t sera padre de v v->padre = p; // printf("Arreglado hacia arriba.\n"); // v ahora es hijo izq de t // t es padre de v v->izq = t; t->padre = v; // el hijo der de t no cambia // printf("Arreglado entre t y v.\n"); // a va a ser hijo derecho de t // t va a ser padre de a t->der = a; a->padre = t; // printf("Arreglado entre a y t.\n"); if (p != NULL) { printf("v = %d es hijo de p = %d,\n", v->id, p->id); } printf("t = %d = %d es hijo de v = %d,\n", t->id, v->izq->id, v->id); printf("a = %d = %d es hijo de t = %d\n", a->id, t->der->id, t->id); printf("b = %d = %d es hijo de v = %d,\n", b->id, v->der->id, v->id); printf("u = %d = %d es hijo de t = %d.\n", u->id, t->izq->id, t->id); // para ni u ni b nada cambia } else { printf("Simple derecha-izquierda.\n"); x1 = a->izq; assert(x1 != NULL); x2 = a->der; assert(x2 != NULL); if (p != NULL) { if (p->izq == t) { p->izq = a; // w } else { // era der. p->der = a; } } else { // t era raiz *raiz = a; // avisar main } v->padre = a; a->der = v; t->padre = a; a->izq = t; v->izq = x2; x2->padre = v; t->der = x1; x1->padre = t; } } else if (ai >= ad + 2) { // voltear hacia la derecha a = u->izq; b = u->der; assert(a != NULL); assert(b != NULL); aalt = a->altura; balt = b->altura; if (aalt >= balt) { printf("Simple derecha.\n"); if (p != NULL) { if (p->izq == t) { p->izq = u; } else { // era derecho p->der = u; } } else { // cambiando la raiz para ser u *raiz = u; } u->padre = p; // printf("Arreglado hacia arriba.\n"); u->der = t; t->padre = u; // printf("Arreglado entre t y u.\n"); t->izq = b; b->padre = t; // printf("Arreglado entre b y t.\n"); } else { // (aalt < balt) printf("Doble izquierda derecha.\n"); x1 = b->izq; assert(x1 != NULL); x2 = b->der; assert(x2 != NULL); if (p != NULL) { if (p->izq == t) { p->izq = b; // w } else { // era der. p->der = b; } } else { // t era raiz *raiz = b; // avisar main } u->padre = b; b->izq = u; t->padre = b; b->der = t; u->der = x1; x1->padre = u; t->izq = x2; x2->padre = t; } } if (p != NULL) { balancea(p, raiz); } } else { printf("%c esta bien (%d vs. %d).\n", n->dato, ai, ad); // siempre checa hasta la raiz balancea(n->padre, raiz); } return; } bool agrega(char dato, nodo* arbol, nodo** n) { nodo* nuevo; nodo* reemplazo; char ruteo; if (arbol == NULL) { // caso especial de no tener nada aun nuevo = (nodo*)malloc(sizeof(nodo)); nuevo->contador = 1; nuevo->id = next++; nuevo->altura = 1; // como hoja nuevo->dato = dato; nuevo->padre = NULL; nuevo->izq = NULL; nuevo->der = NULL; *n = nuevo; // nueva raiz return TRUE; } else { if (arbol->izq == NULL && arbol->der == NULL) { // si es hoja if (arbol->dato == dato) { // iguales; agregar duplicidad arbol->contador++; return FALSE; } printf("Agregando %c en %c.\n", dato, arbol->dato); ruteo = (arbol->dato < dato ? arbol->dato : dato); nuevo = (nodo*)malloc(sizeof(nodo)); nuevo->contador = 1; nuevo->id = next++; nuevo->altura = 1; // como hoja nuevo->dato = dato; nuevo->padre = arbol; nuevo->izq = NULL; nuevo->der = NULL; reemplazo = (nodo*)malloc(sizeof(nodo)); reemplazo->contador = arbol->contador; arbol->contador = NO_VALIDO; reemplazo->id = next++; reemplazo->altura = 1; // como hoja reemplazo->dato = arbol->dato; reemplazo->padre = arbol; reemplazo->izq = NULL; reemplazo->der = NULL; if (dato < arbol->dato) { arbol->izq = nuevo; arbol->der = reemplazo; } else if (dato > arbol->dato) { arbol->der = nuevo; arbol->izq = reemplazo; } arbol->dato = ruteo; arbol->altura = 2; balancea(arbol->padre, n); } else { if (dato <= arbol->dato) { agrega(dato, arbol->izq, n); } else { // mayor agrega(dato, arbol->der, n); } } } return TRUE; } int main(int argc, char** args) { nodo* raiz = NULL; char dato; int contador = 0; do { dato = getchar(); // lee un caracter if (!isspace(dato)) { if (agrega(dato, raiz, &raiz)) { contador++; } if (raiz != NULL) { printf("\nCon %d nodos, altura %d: \n", contador, raiz->altura); muestra(raiz); printf("\n"); } else { printf("No hay nada.\n"); } } } while (dato != '!'); // parar despues de ! borra(raiz); return 1; }
12/7/11
Tarea 5 : Pilas y Colas
La tarea consiste en reutilizar el codigo que se nos proporcionó en clase, para realizarle modificaciones para que funcionara como una pila y una cola.
En clase utilizamos el codigo : listas.c, el cual ordenaba de menor a mayor los datos ingresados, esta funcionalidad no es necesaria en una pila, pues una pila es una estructura en la cual el primer elemento es ingresar es el ultimo en salir y viceversa. En realidad la modificación era quitarle la parte que ordenaba de menor a mayor.
En clase utilizamos el codigo : listas.c, el cual ordenaba de menor a mayor los datos ingresados, esta funcionalidad no es necesaria en una pila, pues una pila es una estructura en la cual el primer elemento es ingresar es el ultimo en salir y viceversa. En realidad la modificación era quitarle la parte que ordenaba de menor a mayor.
#include <stdio.h> #include// imprimir (printf) #include // reservar memoria #include "listas.h" // eliminar todos los elementos de la lista // opcion vaciar elem* borrar(elem* esto) { elem* temp; // auxiliar // iterativa while (esto != NULL) { temp = esto->siguiente; free(esto); // liberar esto = temp; // avanza al siguinte } return NULL; // que ya no hay lista } // checar si la lista contiene un valor dado // devuelve verdad o falso // recibe un puntero a un elemento de la lista // implementacion recursiva bool buscar(int valor, elem* aqui) { if (aqui != NULL) { //#define DEBUG #ifdef DEBUG printf("Buscando por %d en %d.\n", valor, aqui->dato); #endif // hasta aqui si no esta definido DEBUG // si el valor buscado esta en este elemento if (aqui->dato == valor) { #ifdef DEBUG printf("Son iguales.\n"); #endif return TRUE; // busqueda exitosa } else if (aqui->dato > valor) { // ojo: lista esta ordenada de menor // a mayor (por construccion a traves // de la implementacion del metodo // insertar(...) #ifdef DEBUG printf("Ya es mayor. No va a estar.\n"); #endif return FALSE; // busqueda fallida } // pasar la pelota al siguiente elemento return buscar(valor, aqui->siguiente); } else { // aqui es null // este elemento actual ya es null, o sea, // no en realidad es un elemento #ifdef DEBUG printf("Ya se acabo. No estuvo.\n"); #endif return FALSE; // busqueda fallida } } // devuelve si o no se pudo eliminar // (no se puede eliminar si no esta) // valor cuyo elemento hay que eliminar // (unicamente elimina el primer elemento // cuyo valor coincide) // elemento en el cual estamos buscando = aqui // direccion del inicio de la lista bool eliminar_elemento(int valor, elem* aqui, elem** inicio) { if (aqui != NULL) { // si hay algo if (aqui->dato == valor) { // hay que borrar el elemento if (aqui->siguiente != NULL) { aqui->siguiente->anterior = aqui->anterior; } if (aqui->anterior == NULL) { *inicio = aqui->siguiente; } else { aqui->anterior->siguiente = aqui->siguiente; } free(aqui); // borrame return TRUE; // eliminacion exitosa } else if (aqui->dato > valor) { return FALSE; } return eliminar_elemento(valor, aqui->siguiente, inicio); } return FALSE; } // interface para llamadas mas bonitas bool eliminar(int valor, elem** inicio) { return eliminar_elemento(valor, *inicio, inicio); } void imprime_elemento(elem* esto) { // iterativa while (esto != NULL) { printf("%d ", esto->dato); esto = esto->siguiente; } return; } // interfase que agrega [ ... ] y el \n void imprimir(elem* lista) { printf("[ "); imprime_elemento(lista); printf("]\n"); return; } // agregar un elemento en la posicion que // le corresponde (valores de menor a mayor) elem* insertar(int valor, elem* aqui) { elem* nuevo = NULL; // auxiliar // para crear el nuevo elemento //#ifdef DEBUG if (aqui != NULL) { printf("Estoy en %d, insertando un %d.\n", aqui->dato, valor); } else { printf("No hay nada.\n"); } //#endif if (aqui == NULL) { // no hay nadie nuevo = (elem*)malloc(sizeof(elem)); nuevo->dato = valor; // asignar dato nuevo->siguiente = NULL; // el unico nuevo->anterior = NULL; // el unico return nuevo; } else { //if (valor < aqui->dato) { nuevo = (elem*)malloc(sizeof(elem)); nuevo->dato = valor; // pon el valor //if (aqui->anterior == NULL) { // aqui es el primer elemento nuevo->siguiente = aqui; aqui->anterior = nuevo; nuevo->anterior = NULL; return nuevo; /*} else { // un chorro de flechas nuevo->anterior = aqui->anterior; nuevo->siguiente = aqui; nuevo->anterior->siguiente = nuevo; aqui->anterior = nuevo; } } else { // ni igual ni mayor #ifdef DEBUG printf("Insertando algo mayor.\n"); #endif // implementacion recursiva if (aqui->siguiente != NULL) { insertar(valor, aqui->siguiente); } else { // este es el ultimo elemento #ifdef DEBUG printf("Anexando al final.\n"); #endif nuevo = (elem*)malloc(sizeof(elem)); nuevo->dato = valor; nuevo->siguiente = NULL; // el ultimo nuevo->anterior = aqui; aqui->siguiente = nuevo; } } } return aqui; } */ // numeros pseudoaleatorios [MIN, MAX] int pseudoaleatorio() { return ((rand() % (MAX - MIN + 1)) + MIN); } } }
7/7/11
+ Sobre Ciclos
Ahora utilizaré un ciclo for, para pedir las calificaciones de las materias para realizar un promedio.
Este Programa calcula el promedio. El usuario introduce la cantidad de materias y la calificación.
Este Programa calcula el promedio. El usuario introduce la cantidad de materias y la calificación.
#include <stdio.h> int main(int argc, char** args){ int a,c,x,ma; float p=0; printf("Programa que calcula el promedio de x cantidad de materias\n"); printf("Dame el numero de materias de las cuales quieres obtener el promedio\n"); scanf("%d",&x); c=getchar(); ma=x; for(a=1;a<=ma;a++){ printf("Dame la calificacion de la materia %d\n",a); scanf("%d",&x); c=getchar(); p=p+x; } p=p/ma; printf("Tu promedio es de: %f\n",p); return 1; }
Serie de Fibonacci..
Aunque en realidad no es nada nuevo ,decidí agregarlo al blog pues ya he logrado realizarla sin conexion a internet , sin libros y apuntes. Ya hay mejora y eso es motivante. Saludos
#includeint main (int argc, char** args){ int ap,p,a,c;// Inicializamos los valores antepasado,pasado, actual y un contador printf("La serie fibonacci consiste en una secuencia de números \n"); printf("de tal forma que el valor siguiente en la serie es la suma\n"); printf("de sus dos valores anteriores,la serie empieza con 0 y 1\n"); printf("--Este programa determinara los primeros 20 valores de la serie--\n"); ap=0; // Valor antepasado de la serie que seria el 0 p=1; // Valor pasado de la serie es 1 printf("%d\n",ap); printf("%d\n",p); for(c=2; c<=20; c++){ a=ap + p; ap = p; p= a; printf("%d \n",a); } return 1; }
Suscribirse a:
Entradas (Atom)