Schnappschuss vom aktuellen Bildinhalt

dwilx

Schnappschuss vom aktuellen Bildinhalt

Beitrag von dwilx »

Hallo!

Ich suche eine Möglichkeit den Bildinhalt als Schappschuss in Form von Zahlen darzustellen, um evtl. den Zeileninhalt auswerten zu können.
Ich habe irgendwie was von cat /dev/dbox/capture0 gehört, aber bin da nicht so ganz frisch damit. Hat sich da jemand schon mit sowas beschäftigt? Beim Outdoor-Plugin wurde das wohl schon mal verwendet, aber ich will ja nichts abbilden, sondern nur Zahlen rausbekommen, mit denen ich das Bild auswerten kann. Ein Script würde es auch tun.
chkbox
Erleuchteter
Erleuchteter
Beiträge: 440
Registriert: Samstag 10. April 2004, 15:17

Beitrag von chkbox »

Ich verstehe leider nicht ganz, was du meinst. :gruebel: Vielleicht hilft dir, was ich bisher gelernt habe:

Outdoor zeigt eigentlch ganz gut, wie man auf das decodierte MPEG zugreift. In read_frame werden mit read die eigentlichen Daten geholt. Schau dir mal apps/tuxbox/tools/graphics (die aber nicht gehen, siehe unten) an, wie das weiter zu verarbeiten ist.

Leider ind die Treiber hierfür echt Schrott. /dev/dbox/capture0 gehört zur v4l API, da hat der Treiber aber kaum (noch) Funktionen. Außerdem muss man aufpassen, weil die Parameter der ioctl nicht richtig geprüft werden. Falsche Parameter werden mit defektem Fernsehbild bis reboot und/oder Absturz quitiert.
dwilx

Beitrag von dwilx »

Naja, es geht mir hauptsächlich darum, die Zeilen auswerten zu können. Also zB.Zeile 1-576 und dahinter Farbnummern, wenn dass denn irgendwie gehen sollte und ob überhaupt.
cat /dev/dbox/capture0 gibt da irgendwie zu viele (schräge) Sachen raus, die mir erst mal gar nichts sagen.

Das Ergebnis könnte dann irgendwie so aussehen, in Textform:

Code: Alles auswählen

1=196888888888888888816843156387300000000000000000
2=19635555556655516843156387300000000000000000
.
.
.
576=196888888888888888816843156387300000000000000000
Wäre es denn nicht möglich das ganze in ein kleines Tool zu packen, dass diese Rückgabe macht?
Wenn man detailiert wüsste wie das Bild aufgebaut ist, könnte man sich gezielt bestimmte Bildbereiche rauspicken (z.B. bestimmte Zeilenbereiche oben, unten) evtl. könnte man zuverlässig mit WSS das Bildformat steuern, aber das ist einen andere Geschichte!
Npq
Senior Member
Beiträge: 1339
Registriert: Donnerstag 24. April 2003, 12:12

Beitrag von Npq »

chkbox hat geschrieben:Schau dir mal apps/tuxbox/tools/graphics (die aber nicht gehen, siehe unten).
Die sind damals zum Testen des 2.6er Framebuffertreibers geschrieben worden, beim 2.4er funktionieren die nicht (richtig).

Der GTX kann nur ein spezielles deltakodiertes Format capturen, der eNX auch uncompressed, Hauptproblem ist allerdings der zu knappe Demux-Speicher.

Der unsquasher zeigt wie man das deltakodierte Format nach YUY2 wandelt, das Ergebnis müßte wenn ich mich richtig erinnere ein Head-Format sein und - da SD - im ITU-R601-Farbraum vorliegen.
dwilx

Beitrag von dwilx »

Hab wieder mal Zeit etwas daran zu machen. Muss aber sagen, dass ich hier nicht so recht durchblicke. Die Sache mit dem Outdoor-Plugin habe ich mir mal etwas betrachtet und mal als Grundlage rausgenommen und als separates Tool eingebaut. Lasse ich es aber auf der Box laufen, bekomme ich nur ein "Floating point exception" zu sehen. Das sollte aber zumindest erst mal auch gehen bevor man weiter dran rum bastelt.
Ich bin da leider nicht ganz fit was c/c++ angeht, da ich meist auch beruflich nur mit VB/VBA und VBScript zu tun habe. Ich finde das aber ziehmlich "spannend". Der Code ist ja leider nicht so toll dokumentiert :evil: . Evtl. kann mir jemand den Code etwas erläutern.
So wie ich das hier sehe, wird tatsächlich sowas wie ein Screenshot gemacht, allerdings in der Größe 120x65, was eigentlich für meine Zwecke völlig ausreichend wäre. Was mir wichtig wäre, ist eine Funktion, die mir sekündlich (oder variablel) praktisch sowas wie einen "imaginären Zahlenteppich" in der Form einer String-Variablen oder temp-Datei ausgibt, die die C/Y oder RGB Werte aus diesen 120x65 enthält, mit der ich weiter arbeiten kann. Wenn das gegeben wäre, wäre das schon mal super.
Es müsste erst mal die LCD-Anbindung weg und dafür eine andere Ausgabe her. Ich hoffe dass jemand weiterhelfen kann.

Hier der Outdoor Code:

Code: Alles auswählen

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <pthread.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <unistd.h>
#include <fstream>

#include </home/dixidix/tuxbox-cvs/driver/dvb/drivers/media/dvb/avia/avia_gt_capture.h>
#include </home/dixidix/tuxbox-cvs/driver/include/dbox/lcd-ks0713.h>
typedef unsigned char screen_t[LCD_BUFFER_SIZE];

int lcd_fd;
int stride;

inline int compute(int l, int d)
{
	switch (d)
	{
	case 0:
		return l;
	case 1:
		return l+2;
	case 2:
		return l+8;
	case 3:
		return 0x1C;
	case 4:
		return 0x30;
	case 5:
		return 0x44;
	case 6:
		return 0x58;
	case 7:
		return 0x6c;
	case 8:
		return 0x80;
	case 9:
		return 0x94;
	case 10:
		return 0xa8;
	case 11:
		return 0xbc;
	case 12:
		return 0xd0;
	case 13:
		return 0xe4;
	case 14:
		return l-8;
	case 15:
		return l-2;
	default:
		return 0;
	}
}

#define XRES	120
#define YRES	65
//#define XRES	160
//#define YRES  72

void clr() {
	if (ioctl(lcd_fd,LCD_IOCTL_CLEAR) < 0) {
		perror("clr()");
		exit(1);
	}
}

void init() {
	int i;
	if ((lcd_fd = open("/dev/dbox/lcd0",O_RDWR)) < 0) {
		perror("open(/dev/dbox/lcd0)");
		exit(1);
	}
	clr();

	i = LCD_MODE_BIN;
	if (ioctl(lcd_fd,LCD_IOCTL_ASC_MODE,&i) < 0) {
		perror("init(LCD_MODE_BIN)");
		exit(1);
	}
}

void draw_screen(screen_t s) {
	write(lcd_fd, s, LCD_BUFFER_SIZE);
}

void draw_gol(unsigned char *src, screen_t s) 
{
	int x, y, yy, pix;

	for (y=0; y<LCD_ROWS; y++) {
		for (x=0; x<LCD_COLS; x++) {
			pix = 0;
			for (yy=0; yy<8; yy++) {
				pix = (pix<<1) + src[(8*y+yy)*LCD_COLS+x];
			}
			s[y*LCD_COLS+x] = pix;
		}
	}
}

void read_frame(unsigned char *out, int fd)
{
	unsigned short buffer[stride*YRES/2];
	int x, y, lum=0;
	read(fd, buffer, stride * YRES);
	for (y=0; y<YRES; y++)
		for (x=0; x<XRES/2; x++)
		{
			int val=buffer[y*stride/2+x];
			int dy[2]={val&0xF, (val>>8)&0xF};
			lum=compute(lum, dy[1]);
			out[y*XRES+x*2]=lum;
			lum=compute(lum, dy[0]);
			out[y*XRES+x*2+1]=lum;
		}
}

unsigned char image[(LCD_ROWS+1)*LCD_COLS*8], intensity[LCD_ROWS*LCD_COLS*8];

void *update_thread(void*dummy)
{
	unsigned char pic[XRES*YRES];	
	int capture=open("/dev/dbox/capture0", O_RDONLY);
	int x, y;
	
	capture_stop(capture);
	capture_set_input_pos(capture, 0, 0);
	capture_set_input_size(capture, 720, 576);
	capture_set_output_size(capture, XRES, YRES*2);
	stride = capture_start(capture);
	
	printf("Capture driver reports stride=%d\n", stride);
	
	while (1)
	{
		read_frame(pic, capture);
		for (y=0; y<65; y++)
		{
			for (x=0; x<120; x++)
				image[LCD_COLS*y+x]=pic[y*XRES+x];
		}
	}

	capture_stop(capture);
	close(capture);
}

int main(int argc, char *argv[])
{
	
	
	screen_t screen;
	int x, y;
//	int D=atoi(argv[1]);
#define D	3
	// try other values
	pthread_t ut;
	init();
	
	memset(intensity, 0, LCD_ROWS*LCD_COLS*8);
	pthread_create(&ut, 0, update_thread, 0);
	
	for (y=0; y<65; y++)
	{
		for (x=0; x<120; x++)
			image[LCD_COLS*y+x]=0;
	}

	while (1)
	{
		int x, y, yy, pix;
		for (y=0; y<LCD_ROWS; y++) {
			for (x=0; x<LCD_COLS; x++) {
				pix = 0;
				for (yy=0; yy<8; yy++) {
					int off=(8*y+(7-yy))*LCD_COLS+x;
					int val, t=image[off];
					
					if (intensity[off] < t)
						val=1;
					else
						val=0;

					pix = (pix<<1) + val;
					
					intensity[off]=(intensity[off])*(256-D)/256;
					intensity[off]+=val*D;
				}
				screen[y*LCD_COLS+x] = pix;
			}
		}

		draw_screen(screen);
	}
	clr();
	return 0;
}
Carjay
Developer
Beiträge: 122
Registriert: Sonntag 23. April 2006, 12:37

Beitrag von Carjay »

Die LCD-Größe ist eigentlich nicht so interessant, man stellt die Parameter ein, mit denen man capturen will und liest die Daten einfach raus.

Das Problem ist nur, daß der Demux die Daten in einem eigenartigen Format abspeichert. Im CVS liegen da auch noch Tools, die zwar für den 2.6er geschrieben sind, aber das Prinzip ist das gleiche, der Unterschied ist nur, daß beim 2.6er die V4L-API verwendet wird, während im 2.4er eine dbox2-spezifische API benutzt wurde.

Das unsquasher-Tool im CVS enthält die Kernroutine wie man aus dem ausgelesenen Bild die YUY2-Daten bekommt. Daß es einen Header vorneweg erwartet spielt dabei keine so große Rolle, war damals nur bequemer zum Testen.

Wenn du RGB-Daten haben willst, mußt du diese erst dematrifizieren, ich bin mir gerade nicht ganz sicher, aber ich vermute, man braucht die Standard SD-601-Matrix mit Headroom. Das kostet aber auf der dbox2 sehr viel Zeit wenn man es mit Gleitkomma durchführt.

Für Bildanalyse ist YUV aber teilweise sowieso besser geeignet, da hier ja das Luma-Signal bereits vorliegt. Kommt dann darauf an was du damit machen willst.
dwilx

Beitrag von dwilx »

Helldunkelwerte würden, denke ich, auch reichen. Ich würde aber erst einiges durchspielen, um zu sehen was am besten zu gebrauchen ist. Bin für jede Hilfe dankbar!
Beim Ooutdoor-Plugin wird ja im Prinzip auch nur Hell und dunkel ausgegeben, was auch reichen sollte und da sich der Aufwand allein schon wegen dem knappen Speicher in Grenzen halten soll, wäre das sicher angebracht.
Mit dem 2.4er sollte es aber schon noch gehen.
Im Prinzip habe ich mir das so vorgestellt:
Mehrere 1bitBilder im Abstand von einigen Sekunden (oder festlegbarem Intervall) in einem kleinerem Format (zb. 120x96) erzeugen/capturen und eine bestimmte Anzahl als temp. Datei ablegen, die dann zur Auswertung herangezogen werden können. Es sollen aber nicht unendlich viele Bilder erzeugt werden, sondern entweder nach Vorgabe oder von vornherein, sagen wir mal 5 Stück, bei dem immer das älteste entfernt wird und dafür eine neues dazukommt. Die Routinen für die Auswertung selbst sind erst mal daingestellt. Erst mal müssen die Bilder her.
Würde es denn irgendwie gehen die Ausgabe nicht ans LCD sondern in Dateien umzuleiten. Die While-Schleife müsste man aber durch konkrete Intervalle ersetzen. Da blicke aber nicht so richtig durch... :gruebel:
Carjay
Developer
Beiträge: 122
Registriert: Sonntag 23. April 2006, 12:37

Beitrag von Carjay »

Hm, ok, mir scheint, du bist Klassen und Komponenten gewöhnt, die schon alles für dich erledigen, das ist leider hier nicht der Fall.

Du hast nur ein Capture-Device, welches du öffnen kannst. Dann kannst du innerhalb gewisser Grenzen die Parameter (die Größe des erfaßten Bereiches) setzen. "Innerhalb gewisser Grenzen", weil die Hardware dabei bestimmte Größenangaben nicht unterstützt. Ich weiß die gerade nicht mehr auswendig, müßte ich nachschauen.

Sobald du das Capturen startest, übergibst du einfach einen Puffer von ausreichender Größe und dieser wird dann mit den Bilddaten gefüllt.

Die Daten selber sind in einem festen Format, nämlich diesem komprimierten Spezialformat des Demux. Die Routine zum Dekodieren nach YUY2 (das ist ein definiertes YUV-Format, google einfach danach) ist in dem "Unsquasher" oben enthalten.

Die LCD-Routine erzeugt an dieser Stelle direkt 1-Bit Werte. Allerdings ist das LCD etwas merkwürdig organisiert, so daß du den Code vermutlich so nicht direkt übernehmen kannst.

Was du am Ende mit den Daten machst, ist natürlich dir überlassen, es gibt aber keine Instanz, die das was du vorhast automatisch durchführt, das mußt du schon selber schreiben.
dwilx

Beitrag von dwilx »

Hm, ok, mir scheint, du bist Klassen und Komponenten gewöhnt, die schon alles für dich erledigen, das ist leider hier nicht der Fall.
Nu ganz so isses nicht. Bin nur nicht auf der C/C++ Schiene zu hause und tu mich da etwas schwer beim Codelesen. Aber Danke erstmal.
Die Bilder da raus zu bekommen ist primär. Die Auswertung hinterher bekomme ich dann schon hin. Ich hoffe aber, dass ich weiter auf Unterstützung zählen kann?