Bitmap-Bilder einlesen, bearbeiten und erzeugen



  • Jetzt habe ich eine ganz konkrete Frage.

    Nach dem ich das Dunkelbild vom astronomischen Bild pixelweise abgezogen habe, was mache ich mit den entstehenden Minuswerten? Ich vermute sie werden invertiert. Benutzt man da , dass zweierkompliment?


  • Mod

    @yberion45 sagte in Bitmap-Bilder einlesen, bearbeiten und erzeugen:

    Nach dem ich das Dunkelbild vom astronomischen Bild pixelweise abgezogen habe, was mache ich mit den entstehenden Minuswerten? Ich vermute sie werden invertiert. Benutzt man da , dass zweierkompliment?

    Da gibt es keine programmiertechnische Antwort drauf, da muss man mitdenken, wie das Ding wohl funktioniert. Da das eine Übungsaufgabe ist und kein echtes Gerät, gibt es keine richtige Antwort. Wenn man aber mal überlegt, wie so ein Sensor wohl funktioniert, und mal auch damit vergleicht, wie handelsübliche Kameras funktionieren, dann: Nein, da sollte man gewiss nicht invertieren. Wenn du sagst, dass Werte unter 0 besonders hellen Werten entsprechen, dann hieße das ja, dass dein Sensor überlaufen kann. Hast du jemals eine Kamera gesehen, bei der eine Lichtquelle wieder schwarz wird, wenn sie zu hell ist? Ich nicht. Es wäre ziemlicher Unsinn, einen Kamerasensor so zu konstruieren.



  • @seppj so, da ich mich mit sowas nicht auskenne, heißt das Konkret? Werte unter 0 wird es nicht geben da die Farbe Schwarz 0 ist. Was mache ich mit den negativen Werten?

    oder habe ich mich verrechnet? oder kommt das durch falsches Einlesen?

    also ich habe zum Test die orginal Datei eingelesen und dann getrennt und wieder zusammen gesetzt und das Orginal Bild kam wieder raus. Daher denke ich, dass es richtig ist. Ich lese in ein char Array ein. Ich würde die negativen Werte alle zu 0 machen, was mir so einfällt.

    Muss man die ausgelesenen Werte in RGB Werte umwandeln um dann eventuell zu rechnen?

    {
    	int x=0,y=0;
    	double z1[150][100],z2[150][100];
    
    	for(x = 0; x < 150; x++)
    	{
    		for( y = 0; y < 100; y++)
    		{
    			z1[x][y] = *(pixeldark + x*100 + y);
    			z2[x][y] =*(pixelraw + x * 100 + y);
    			z2[x][y] -= z1[x][y];					// Überlegen was mit negativen Werten zu machen ist!
    
    		}
    	}
    
    	for(x = 0; x < 150; x++)
    	{
    		for( y = 0; y < 100; y++)
    		{
    			printf("%.2lf\t",z2[x][y]);
    
    		}
    		putchar('\n');
    	}
    
    
    }
    
    
     ...1 Rechnung ... 
    

    Das Würde ich drunter setzen:

     ... Code ... 
    if(z2[x][y] < 0) z2[x][y] =0;
    

    Ich habe grad mal geschaut, die Werte die er mir anzeigt sind RGB Werte, und es gibt keine Negativen Werte somit würde ich behaupten, dass die negativen Werte zu 0 werden. Das wäre mein logisches Mitdenken eventuell füge ich mal orginal Bild später ein und zeige mal was dabei rauskommt
    So würde meine Komplette Berechnung aussehen:

     ... Code ... 
    	for(x = 0; x < 150; x++)
    	{
    		for( y = 0; y < 100; y++)
    		{
    			z1[x][y] = *(pixeldark + x*100 + y);
    			z2[x][y] =*(pixelraw + x * 100 + y);
    			z2[x][y] -= z1[x][y];					// negative Werte werden zu 0, Rohbilddaten -Rohwerte schwarz
    			if(z2[x][y] < 0) z2[x][y] =0;
    
    		}
    	}
    
    	for(x = 0; x < 150; x++)
    	{
    		for(y = 0; y < 100; y++)
    		{
    			z2[x][y] /=(double)*(pixelwhite + x *100 +y); //division durch Rohwerte vom weißen Bild
    			z2[x][y] *= getMittelwert(pixelwhite);   //Mal den Mittelwert eventuell hier ein Fehler? alle Werte von weißen Rohbild addiert und durch 100*150 geteilt;
    			z2[x][y] = round(z2[x][y]);    //ganz Zahlen auf oder abrunden
    
    		}
    	}
    


  • So hab den Code mal fertig geschrieben und hoffe jetzt auf sachliche Hilfe.
    Ich füge auch die Bilder vom Orginal und der Erzeugten Datei hinzu. Bitte mir mögliche Fehler nennen. Ich wäre euch so dankbar!

     ... Code ... 
    int main(int argc,char *argv[])
    {
    	FILE *AS1,*white,*dark,*AS2;
    	unsigned  char header[1078];
    	unsigned char pixeldark[150][100],pixelwhite[150][100],pixelraw[150][100];
    	BYTE pixeledit[150][100];
    
    
    	if(argc <=5)
    		fprintf(stderr,"Keine Argumente!\n"),exit(0);
    	else
    		printf("Argumente wurden gefunden!\n");
    
    	AS1 = fopen(argv[1],"rb");
    	AS2 = fopen(argv[2],"rb");
    	white = fopen(argv[5],"rb");
    	dark = fopen(argv[4],"rb");
    
    
    	if(AS1 == NULL || white == NULL || dark == NULL || AS2 == NULL)
    		fprintf(stderr,"Datei konnte nicht geöffnet werden!\n"),exit(0);
    	else
    	 printf("Datei wurde geoffnet!\n");
    
    	getPixel(dark,header,&pixeldark[0][0]);
    	getPixel(white,header,&pixelwhite[0][0]);
    	getPixel(AS2,header,&pixelraw[0][0]);
    	ImageEdit(&pixelraw[0][0],&pixelwhite[0][0],&pixeldark[0][0],&pixeledit[0][0]);
    	createPic(&pixeledit[0][0],header);
    
    	fclose(AS1);
    	fclose(AS2);
    	fclose(white);
    	fclose(dark);
    	return 0;
    }
    
    void getPixel(FILE *bild, unsigned char *Vorspann,  unsigned char *array)
    {
    	int i =0,x=0,y=0;
    	unsigned int width,height;
    
    
    	for( i = 0; i < 1078; ++i){
    		Vorspann[i] = fgetc(bild);}
    
    		if(Vorspann[0] != 'B' || Vorspann[1] != 'M'){
    			printf("Es ist keine BMP Datei!\n"),exit(0);}
    		else
    		{
    			printf("Es handelt sich um eine BMP Datei!\n");
    		}
    
    	width = (int)Vorspann[0x12];
    	height = (int)Vorspann[0x16];
    
    
    
    	fseek(bild,0x436,SEEK_SET);
    
    	for(x = 0; x < height; x++)
    	{
    		for(y = 0; y < width; y++)
    		{
    
    			*(array + x* width + y) = fgetc(bild);
    		}
    	}
    
    
    
    
    
    
    
    }
    
    double getMittelwert(unsigned char *whitepic)
    {
    	double mittelwert=0;
    	int x=0,y=0;
    
    	for(x = 0; x < 150; ++x)
    	{
    		for(y = 0; y < 100; ++y)
    		{
    			mittelwert = mittelwert + *(whitepic + x*100 +y);
    		}
    	}
    
    	mittelwert = mittelwert/ (150*100);
    
    	return mittelwert;
    }
    
    void ImageEdit( unsigned char * pixelraw, unsigned char *pixelwhite,unsigned char *pixeldark,BYTE *pixeledit)
    {
    	int x=0,y=0;
    	double z1[150][100],z2[150][100];
    
    	for(x = 0; x < 150; x++)
    	{
    		for( y = 0; y < 100; y++)
    		{
    			z1[x][y] = *(pixeldark + x*100 + y);
    			z2[x][y] =*(pixelraw + x * 100 + y);
    			z2[x][y] -= z1[x][y];					// Überlegen was mit negativen Werten zu machen ist!
    			if(z2[x][y] < 0) z2[x][y] =0;
    			z2[x][y] /=(double)*(pixelwhite + x *100 +y);
    			z2[x][y] *= getMittelwert(pixelwhite);
    			z2[x][y] = round(z2[x][y]);
    			*(pixeledit + x*100 +y) = z2[x][y];
    
    		}
    	}
    
    
    
    
    }
    
    void createPic(BYTE *pixelraw,unsigned char *header)
    {
    	FILE *test;
    	int i =0,x=0,y=0;
    
    	test = fopen("test.bmp","wb");
    
    
    	fseek(test,0,SEEK_SET);
    
    	for(i = 0; i < 1078; ++i)
    		putc(header[i],test);
    
    	fseek(test,1078,SEEK_SET);
    
    	for(x = 0; x < 150; x++)
    	{
    		for(y = 0; y < 100; y++)
    		{
    			putc(*(pixelraw + x*100 +y),test);
    		}
    	}
    	putc(0,test);
    	putc(0,test);
    
    
    
    
    }
    
    

    Orginal Bild

    ausgabe bearbeitet

    und ich glaube nicht das die Ausgabe so richtig ist. hmm



  • Hey Leute
    ich habe es hinbekommen und habe den Compiler die Arbeit machen lassen.

    Der Knackpunkt bei der Rechnung ist, das man beim subtrahieren einfach unsigned char nimmt und der die Werte selbstständig subtrahiert und macht. Nach dem man subtrahiert hat und durch das Weiß Bild dividiert hat , sind die Werte alle zwischen 0 und 1. Dann nach der Multiplikation sind die alle 0 oder 249. Als Ergebnis kommt ein Sternenhimmel raus. Mal sehen ob das Ergebnis akzeptiert wird. Da ich anderen helfen will die zufällig diese Aufgabe in der Fachhochschule bekommen, poste ich mein Ergebnis hier. Ich möchte auch drauf hin weißen, dass der Code vom Cobain komplett falsch ist und vorne und hinten nicht funktionieren wird. Einfach zum Ende scrollen !

     ... main.c... 
    
    /*
     * Author		: yberion45
     * Name			: main.c
     * Datum		: 25.10.2018
     * Martriknr	: 
     * Beschreibung : Hier werden die Bilder eingelesen, verschiedene Kontrollen gemacht und dann an die Funktion zur Bildbearbeitung geschickt
     */
    
    #include "Bildbearbeitung.h"
    
    
    int main(int argc,char *argv[])
    {
    	FILE *Bild;											//Deklaration der Variablen
    	unsigned  char header[1078];
    	unsigned char pixeldark[150][100],pixelwhite[150][100],pixelraw[150][100];
    	char name[14],endung[9]={'k','o','r','r','.','b','m','p'};
    	int i=0,j=0,k=0,posdark=0,poswhite=0,pos=0,m=0;
    
    
    
    
    	if(argc <=5)		//Weniger als 5 Argumente Fehler!
    	{
    		fprintf(stderr,"Keine Argumente!\n"),exit(0);
    	}
    	else
    	{
    		printf("Argumente wurden gefunden!\n");
    	}
    
    
    		for(k = 1; k < argc; ++k)					//Schleife zum Suchen der dark.bmp und white.bmp
    		{
    				if((strcmp(argv[k],"dark.bmp")) == 0)			//Wenn findet hol die Pixel ab und speichere die Position des Arguments
    				{
    					Bild = fopen(argv[k],"rb");
    					getPixel(Bild,header,&pixeldark[0][0]);
    					posdark = k;
    				}
    				if((strcmp(argv[k],"white.bmp")) == 0)
    				{
    					poswhite = k;
    					Bild=fopen(argv[k],"rb");
    					getPixel(Bild,header,&pixelwhite[0][0]);
    
    				}
    		}
    
    
    
    		pos = argc-1;			//Anzahl der Arguemnte
    
    
    		if( posdark > 3 && poswhite > 3)		//wenn dark.bmp oder white.bmp hintere Pos laufe nur bis vor den beiden
    		{
    			if( posdark > poswhite)
    			{
    				pos = poswhite;
    			}
    			else if( posdark < poswhite)
    			{
    				pos = posdark;
    			}
    			m=0;
    		}
    		else if( posdark < 2 && poswhite <= 2)		//Wenn dark.bmp und white bmp vorne fange ab Position 2 an
    		{
    			m=2;
    		}
    
    
    	for( k = m; k < pos -1 ; ++k)					//Scheife für die Bildbearbeitung
    	{
    
    
    			if(k == posdark)		//Wenn dark.bmp und white bmp nicht den Platz ganz vorne oder ganz hinten haben
    				continue;
    			if(k == poswhite)
    				continue;
    
    			Bild = fopen(argv[k+1],"rb");			//Öffne Bild!
    
    			if(Bild == NULL)										//Konnte Bild geöffnet werden?
    				printf("Bild wurde nicht gefunden!\n"),exit(0);
    
    			getPixel(Bild,header,&pixelraw[0][0]);					//Hole die Pixel vom Rohbild und den Header
    			ImageEdit(&pixelraw[0][0],&pixelwhite[0][0],&pixeldark[0][0]);		//Bearbeite das Bild
    
    
    
    			strncpy(name,argv[k+1],4);				//Kopiere Name vom Argument bis vor den Punkt
    
    			for(i = 4,j=0; j < 9; ++j , ++i)		//Füge den Name für die Ausgabe Datei hinzu korr.bmp
    			{
    				name[i] = endung[j];
    			}
    
    				name[i] = '\0';
    
    
    
    			createPic(&pixelraw[0][0],header,name);		//Gebe Bild aus!
    
    	}
    
    	fclose(Bild);				//schließe Bild
    	return 0;
    }
    
    
     ... bildbearbeitung.c …
    
    /*
     * Author		: yberion45
     * Name			: Bildbearbeitung.c
     * Datum		: 25.10.2018
     * Martrikelnr	: 
     * Beschreibung : Hier sind die ganzen Funktion um das Bild zu bearbeiten und auszugeben!
     */
    
    #include "Bildbearbeitung.h"
    
    
    
    /*
     * Name			: getPixel
     * Datum		: 25.10.2018
     * Beschreibung	: Hier wird im ersten Schritt Der Vorspan der BMP Datei in ein Array gespeichert und
     * 				  anschließend werden die Pixel aus der BMP Datei ausgelesen
     */
    
    
    void getPixel(FILE *bild, unsigned char *Vorspann,  unsigned char *array)
    {
    	int i =0,x=0,y=0;
    	unsigned int width,height;
    
    	for( i = 0; i < 1078; ++i)			// Der Vorpann wird ausgelesen
    	{
    		Vorspann[i] = fgetc(bild);
    	}
    
    		if(Vorspann[0] != 'B' || Vorspann[1] != 'M')			//Ist es eine BMP Datei, wenn nicht exit
    		{
    			printf("Es ist keine BMP Datei!\n"),exit(0);
    		}
    		else
    		{
    			printf("Es handelt sich um eine BMP Datei!\n");
    		}
    
    	width = (int)Vorspann[0x12];								//Abholen der Spalten und Zeilen
    	height = (int)Vorspann[0x16];
    
    
    
    	fseek(bild,0x436,SEEK_SET);					//Positioniere Zeiger auf der Position 0x436
    
    	for(x = 0; x < height; x++)					// Spalten Schleife
    	{
    		for(y = 0; y < width; y++)				//Zeilen schleife
    		{
    
    		  *(array + x* width + y) = fgetc(bild);		//lese Pixel ein und speichere sie im 2D Array
    		}
    	}
    
    
    
    
    }
    
    /*
     * Name			: getMittelwert
     * Datum		: 25.10.2018
     * Beschreibung : Hier wird der Mittelwert der  WeißBild berechnet
     */
    
    double getMittelwert(unsigned char *whitepic)
    {
    	double mittelwert=0;
    	int x=0,y=0;
    
    	for(x = 0; x < 150; ++x)			//Spalten Schleife
    	{
    		for(y = 0; y < 100; ++y)		//Zeilen Schleife
    		{
    			mittelwert = mittelwert + *(whitepic + x*100 +y);
    		}
    	}
    
    	mittelwert = mittelwert/ (150*100);		//teilen durch die Gesamt Anzahl
    
    	return mittelwert;
    }
    
    /*
     * Name			: ImageEdit
     * Datum		: 25.10.2018
     * Beschreeibung: Hier wird das Bild bearbeitet. Erst wird Das SchwarzBild subtrahiert und dann das Weiß Bild dividiert und anschließend
     * 				 mit dem Mittelwert multipilziert und gerundet;
     */
    
    void ImageEdit( unsigned char * pixelraw, unsigned char *pixelwhite,unsigned char *pixeldark)
    {
    	int x=0,y=0;
    	double z1[150][100];
    	double graustufenmittelwert=0;
    
    	graustufenmittelwert = getMittelwert(pixelwhite);			//Abholen des Mittelwertes!
    
    			for(x = 0; x< 150; x++)					//Spaltenschleife
    			{
    				for(y = 0; y<100; y++)				//Zeilenschleife
    				{
    					*(pixelraw + x*100 +y) = *(pixelraw + x*100 +y) - *(pixeldark + x*100 +y);  // Rohbild - Dunkelbild
    					z1[x][y] = *(pixelraw + x*100+y) / (*(pixelwhite + x*100 +y));				//korrigiertes Rohbild/weißbild
    					z1[x][y] = z1[x][y] *graustufenmittelwert;									// korrigiertes Rohbild mal Mittelwert
    					z1[x][y] = round(z1[x][y]);													//Runden
    					*(pixelraw + x*100 +y) = z1[x][y];											//Speichern im Rohbild array
    				}
    			}
    
    
    
    }
    
    /*
     * Name			: createPic
     * Datum		: 25.10.2018
     * Beschreibung :  Hier wird das Bild ausgegeben mit dem neuen Dateinamen
     */
    
    void createPic(unsigned char *pixelraw,unsigned char *header,char *name)
    {
    	FILE *ausgabe;
    	int i =0,x=0,y=0;
    
    
    	ausgabe = fopen(name,"wb");			//öffnen der Datei mit dem neuen Namen.
    
    
    
    
    	fseek(ausgabe,0,SEEK_SET);			//Positioniere Zeiger auf Pos 0 in der Ausgabe Datei
    
    	for(i = 0; i < 1078; ++i)			// Schreibe den Vorspann der BMP Datei in die Ausgabe datei
    		fputc(header[i],ausgabe);
    
    	fseek(ausgabe,1078,SEEK_SET);		//Positioniere den Zeiger auf die Position 1078 in der Dati
    
    	for(x = 0; x < 150; x++)
    	{
    		for(y = 0; y < 100; y++)
    		{
    
    			fputc(*(pixelraw + x*100 +y),ausgabe);  		//Schreibe die korrigierten Pixel in die Datei
    
    		}
    	}
    	putc(0,ausgabe);										//Hänge die Füllbytes dran
    	putc(0,ausgabe);
    
    
    }
     
    
     ... Header.h... 
    /*
     * Bildbearbeitung.h
     *
     *  Created on: 25.10.2018
     *      Author: tiger
     */
    
    #ifndef BILDBEARBEITUNG_H_
    #define BILDBEARBEITUNG_H_
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <math.h>
    
    extern void getPixel(FILE *,  unsigned char *,unsigned char *);
    extern void ImageEdit( unsigned char *, unsigned char *,unsigned  char *);
    extern double getMittelwert(unsigned char *);
    extern void createPic(unsigned char *,unsigned char*,char *);
    
    #endif /* BILDBEARBEITUNG_H_ */
    
    


  • @yberion45 Hi, als hättest du es gewusst muss nun auch ich diese Aufgabe lösen. Wo muss ich denn die Bilder ablegen, damit das Programm diese erkennt? Danke im Voraus.



  • @MarioLuigi sagte in Bitmap-Bilder einlesen, bearbeiten und erzeugen:

    Wo muss ich denn die Bilder ablegen, damit das Programm diese erkennt?

    Abgesehen davon, das der letzte Post 3 Monate her ist, wollte ich selbst mal schauen und will versuchen eine Antwort zu geben, mit dem Wissen, das C für mich schon etwas anstrengend unbekannt ist und in der Hoffnung korrigiert zu werden.

    FILEscheint ein eigener Datentyp zu sein, der die Bildquelle darstellen soll. Ich erkenne aber nirgendwo die Definition dafür. Außer "Bildbearbeitung.h"wird ja nichts anderes eingebunden?



  • FILE kommt aus der stdio.h und es ein eigener datentyp (eine struktur meine ich) für dateien. in der praktischen anwendung unterscheidet er sich nicht aber nicht von der unter unix üblichen vorgehensweise einen integer zu deklarieren, mit dem unterschied, dass man funktionen mit einem f davor verwenden muss.



  • Ok, danke 😉



  • @MarioLuigi sagte in Bitmap-Bilder einlesen, bearbeiten und erzeugen:

    Wo muss ich denn die Bilder ablegen, damit das Programm diese erkennt?

    • Wenn du in deinem Code nur den Dateinamen angibst, wird üblicherweise (UN*X, Windows) im Arbeitsverzeichnis (Current Working Directory, cwd) gesucht.
    • Gibst du einen relatifen Pfad an ( zB. ../../foo/bar/qux.bmp), so ist dieser relativ zum CWD.
    • Bei vollständigen Pfaden sollte die Sache klar sein.

    Was anderes: Nicht ausgraben drei Jahre alte Threads, du sollst, junger Padawan. Aufmachen neuen Thread nächstes Mal mit deiner Frage du solltest.



  • @MarioLuigi: Den Code von @yberion45 solltest du aber nicht übernehmen, denn die Ressourcenverwaltung (z.B. Schließen der geöffneten Dateien) ist mangelhaft.
    Auch die Verwendung der Konstanten (für Arraygrößen und Schleifendurchläufe) - anstatt dynamisch aus der BMP-Datei - ist überarbeitungswürdig.



  • @Swordfish Ok, danke für die Antwort. Ich keine alten Threads mehr ausgraben werde, mein Meister. Da ich aber noch sehr frisch bin was C angeht, verstehe ich noch nicht so ganz wie ich dem Programm jetzt die Bilder übergebe.

    Hatte ein Programm entdeckt, was ein paar Bilddaten ausgibt. Da ist das mit dem Einlesen verständlich, weil da nur ein Bild betrachtet wird indem einfach der Pfad eingegeben wird.
    In dem Programm oben müssen aber ja 5 Bilder betrachtet werden. Wenn man nun unter Windows die 5 Bilder einfach auf die exe "zieht", dann steht da zwar "Argumente wurden gefunden!" und "Es handelt sich um eine BMP Datei". Danach schließt sich die exe aber wieder.

    int main()
    {
        unsigned char bilddaten[54];
    
        char name[40];
    
        int byte;
        int index=0;
    
        printf("Hier bitte Pfad der BMP Datei eingeben\n");
        scanf("%s",&name);
    
        FILE * file;
    
        file = fopen(name, "rb");
    
        if (file !=NULL){
            do{
                byte=fgetc(file);
                bilddaten[index]=byte;
    
                index++;
    
                if (index==54)break;
            }while (byte!=EOF);
        }else {
            for (int i=0;i<29;i++){
                    bilddaten[i]='\0';
    
            }
            }
        fclose(file);
    
        int breite = bilddaten [20-1]*256 +bilddaten[19-1];
        int hoehe = bilddaten [24-1]*256 + bilddaten[23-1];
        int bits = bilddaten [29-1];
    
        printf("\nBreite: %d \nLaenge: %d\nBits: %d",breite, hoehe ,bits);
    
     
        return 0;
    
    }


  • @Swordfish sagte in Bitmap-Bilder einlesen, bearbeiten und erzeugen:

    Aufmachen neuen Thread nächstes Mal mit deiner Frage du solltest.

    Was war daran unverständlitsch? @Mods: Close please.

    Deine Frage hat nichts mit diesem Thread zu tun.


Anmelden zum Antworten