TweakPC

Zurück   Computer Hardware Forum - TweakPC > Games und Software > Programmiersprachen

Antwort
 
LinkBack Themen-Optionen Ansicht
Alt 26.09.2010, 08:19   #1 (permalink)
Extrem Tweaker
 
Benutzerbild von kanonenfutter
 

Registriert seit: 10.07.2006
Beiträge: 2.290

kanonenfutter ist ein Lichtblickkanonenfutter ist ein Lichtblickkanonenfutter ist ein Lichtblickkanonenfutter ist ein Lichtblickkanonenfutter ist ein Lichtblick

Frage [C++] Problem bei Denkaufgabe

Hi Leutz

Also ich sitze gerade an einem Programm, welches ich als Projekt in der Uni abgeben muss. Thema: Demonstration von Bildverarbeitungsbefehlen in C++. So weit so gut. Mein Problem hier ist allerdings sehr allgemeiner Kultur, hat also nicht viel mit C++ oder BV im speziellen zu tun.

Und zwar folgendes: Ich habe ein Fenster mit einem Bild drin. Außerdem ist in dem Fenster ein Balken (quasi ein Schieberegler), über den ich einen Wert alpha einstellen kann (von 0 bis 1). Umso höher alpha, desto stärker wird das Bild geschärft. Ich arbeite über das gesamte Projekt hinweg (dies hier ist nur eine Teilaufgabe) mit der Bibliothek "CImg". Ich verwende daher keine normale Windowsoberfläche (da nicht möglich), sondern bastel mir meine wenigen benötigten Eingabeelemente einfach selbst

Mal kurz zur Vorstellung:

http://www.tweakpc.de/forum/members/...e1641-bv-c.jpg

Mittlerweile hab ich nach einigem geistigem Spagat schonmal geschafft, dass die Höhe des Balkens korrekt gezeichnet wird, je nach eingestelltem alpha.

Mein Problem nun ist, dass ich aus der y-Position des Mausklicks (Achtung: beim Bildkoordinatensystem liegt der Ursprung links oben, y wird nach unten also immer größer), das entsprechende alpha berechnen muss. Hierzu hab ich zwar schon mehrere in Frage kommende Formeln durch, allerdings liefert keine das Ergebnis das ich suche.

Ich möchte mal kurz die verwendeten Maße versuchen zu verdeutlichen. Das Bild ist fest 450px hoch, über und unter dem Balken befinden sich jeweils 25px+Schriftgröße (im aktuellen Fall bei Schriftgröße 24 = insgesamt 49px) Platz zum Fensterrand.

Der unterste Punkt für alpha = 0 lässt sich also durch 450 - schriftgröße - 25 (= 401)angeben, der oberste für alpha = 1 durch schriftgröße + 25 (= 49).

Hier mal mein aktueller Quelltext zum Problem:

Code:
1)    const int yb = (int)((450-tsize-25)-(alpha*(450-50-(2*tsize))));
    
2)            visu[1].draw_rectangle(38, 450-tsize-23, 62, tsize+23, lblue, 1).
            draw_rectangle(39, 450-tsize-24, 61, tsize+24, dblue, 1).draw_rectangle(40, 450-tsize-25, 60, yb, blue, 1);
    
3)            if ((disp.button()) && (disp.mouse_x()>=img.width() + 38) && (disp.mouse_x()<=img.width() + 62) && 
                (disp.mouse_y()>=tsize + 25) && (disp.mouse_y()<=450-tsize-25))
            {
4)                alpha = ((disp.mouse_y() -450 +25 +tsize) / ((50 +(2*tsize) -450)/100));
                  alpha/= 100;

5)                if(alpha>0.999)
                {
                    alpha = 0.999;
                }
            }
1) hier wird yb berechnet, welches die Höhe des Balkens angibt in Abhängigkeit von alpha, funzt wunderbar

2) da wird einfach nur der Balken gezeichnet an die entsprechenden Koordinaten

3) Sobald in dem Balken ein Mausklick registriert wird...

4) ...berechne das zugehörige alpha aus der y-Position des Klicks (bei dieser Formel liegt der Hund begraben, aktuell habe ich die obere Formel von yb genommen und nach alpha umgestellt und für yb die y-Mauskoordinate angenommen)

5) sollte alpha größer werden als 0,999 setze es au 0,999, soll einfach verhindern das Werte mit 1 angenommen werden können, da dann die Schärfeformel Müll rechnet

Tja, so wie ich das im Moment so stehen habe, ergibt sich folgendes Problem, umso weiter ich den Balken nach oben schieben will, desto weiter eilt der Balken meiner Maus voraus. In den unteren Regionen bei alpha ca. 0,1 stimmt die Balkenposition mit der Mausposition überein. Umso größer das alpha wird, umso größer auch der Fehler. Hab leider keine Ahnung mehr woran das liegen kann. Irgend einen einfachen Offset kann ich nicht vergessen haben, da sonst über den gesamten Balkenverlauf der Fehler (Distanz y-Balkenposition zu y-Mausposition) immer gleich groß wäre. In meinem Fall jedoch nimmt er mit kleinerer y-Mauskoordinate zu...

Wäre schön wenn jmd. eine Idee liefer könnte, bin mit meinem Latein am Ende,hoffe ich konnte es ausreichend rüberbringen

mfg
kanonenfutter
kanonenfutter ist offline   Mit Zitat antworten
Alt 26.09.2010, 11:09   #2 (permalink)
Hardware Freak
 

Registriert seit: 28.03.2003
Beiträge: 8.252

redfalcon kann auf vieles stolz sein
redfalcon kann auf vieles stolz sein

Standard AW: [C++] Problem bei Denkaufgabe

Haben alpha und disp.mouse_y die selben Datentypen?

Ich würde mir zuerst mal Debug-Ausgaben für alpha und disp.mouse_y machen, dann sieht man in welchen Wertebereichen die Variablen auseinanderlaufen. Ich vermute, dass ein Offset mit sinkendem y-Wert zuviel draufgerechnet wird.
Den kompletten Quelltext kannst du nicht hochladen, oder?
redfalcon ist offline   Mit Zitat antworten
Für diesen Beitrag bedankt sich:
kanonenfutter (26.09.2010)
Alt 26.09.2010, 12:16   #3 (permalink)
Extrem Tweaker
 
Benutzerbild von kanonenfutter
 

Registriert seit: 10.07.2006
Beiträge: 2.290

kanonenfutter ist ein Lichtblickkanonenfutter ist ein Lichtblickkanonenfutter ist ein Lichtblickkanonenfutter ist ein Lichtblickkanonenfutter ist ein Lichtblick

Standard AW: [C++] Problem bei Denkaufgabe

Tja, also alpha ist ein double, disp.mouse_y() ist ein integer.

Kompletter Quelltext:

Code:
#include "CImg.h"
using namespace cimg_library;

int main()
{
    CImg<int>img("leucht.jpg");
    CImgList<double>visu(img, CImg<int>(100,450,1,3,0));
    CImgDisplay disp(visu,"Test");
    
    int pw, mw, neu, i, j, valR, valG, valB, avg = 0;
    int tsize = 24;

    const unsigned char white[] = {255,255,255};    
    const unsigned char blue[] = {0,0,255};    
    const unsigned char lblue[] = {0,0,192};    
    const unsigned char dblue[] = {0,0,128};

    for (double alpha = 0.5; !disp.is_closed() && !disp.is_keyQ() && !disp.is_keyESC(); ) 
    {
        for(int x=1; x<img.width()-1; x++)
        {
            for(int y=1; y<img.height()-1; y++)
            {        
                pw = img(x,y,0,0);
                mw = 0;
    
                for(i=-1; i<=1; i++)
                {
                    for(j=-1; j<=1; j++)
                    {
                        mw += img(x+i, y+j, 0, 0);
                    }
                }

                mw /= 9;
                neu = (int)((pw - (alpha*mw)) / (1.0-alpha));

                if(neu > 255)
                {
                    neu = 255;
                }
                else if(neu < 0)
                {
                    neu = 0;
                }
                visu[0](x,y,0,0) = neu;

                valR = visu[0](x,y,0,0);                    // Read the red component
                valG = visu[0](x,y,0,1);                    // Read the green component
                valB = visu[0](x,y,0,2);                    // Read the blue component (Z


                avg = (int)((valR + valG + valB)/3);            // Compute average pixel value.

                visu[0](x,y,0,0) = visu[0](x,y,0,1) = visu[0](x,y,0,2) = avg;    //Graubild                
                
            }
        } 

        visu[1].fill(0).draw_text(25,5,"Alpha",white,0,1,tsize).
            draw_text(35,450-tsize-5,"%.2f",white,0,1,tsize,alpha);
        visu[0].draw_line(img.width()-1,0,img.width()-1,img.height(),white,1);
    
        const int yb = (int)((450-tsize-25)-(alpha*(450-50-(2*tsize))));
    
        visu[1].draw_rectangle(38, 450-tsize-23, 62, tsize+23, lblue, 1).
        draw_rectangle(39, 450-tsize-24, 61, tsize+24, dblue, 1).draw_rectangle(40, 450-tsize-25, 60, yb, blue, 1);
    
        if ((disp.button()) && (disp.mouse_x()>=img.width() + 38) && (disp.mouse_x()<=img.width() + 62) && 
            (disp.mouse_y()>=tsize + 25) && (disp.mouse_y()<=450-tsize-25))
        {
            alpha = ((disp.mouse_y() -450 +25 +tsize) / ((50 +(2*tsize) -450)/100));
            alpha/= 100;

            if(alpha>0.999)
            {
                alpha = 0.999;
            }
        }

        disp.resize(disp,false).display(visu).wait();
    }
}
Kommentare zu jeder einzelnen Zeile spare ich mir mal

mfg
kanonenfutter ist offline   Mit Zitat antworten
Alt 26.09.2010, 13:31   #4 (permalink)
Hardware Freak
 

Registriert seit: 28.03.2003
Beiträge: 8.252

redfalcon kann auf vieles stolz sein
redfalcon kann auf vieles stolz sein

Standard AW: [C++] Problem bei Denkaufgabe

So funktioniert es, ich weiss aber noch nicht ganz warum. Bei deiner Berechnung bekommt alpha zwar Werte, allerdings nur stark gerundete. In meiner Version kommen da viel genauere Werte raus. Mit sinkendem y-Wert wird der Unterschied dann immer gravierender, daher wohl die Verschiebung.

Code:
//Bei dir vermutlich anders:
//#define cimg_graphicsmagick_path 'D:\GraphicsMagick'
#include "CImg.h"
#include <iostream>
using namespace cimg_library; 
using namespace std;

int main()
{
	CImg<int>img("leucht.jpg");
    CImgList<double>visu(img, CImg<int>(100,450,1,3,0));
    CImgDisplay disp(visu,"Test");
    
    int pw, mw, neu, i, j, valR, valG, valB, avg = 0;
    int tsize = 24;
	double upperOffset = tsize+25;
	double lowerOffset = 450-tsize-25;
	double offsetMod =  2;
	double oldalpha = 0.0;

    const unsigned char white[] = {255,255,255};    
    const unsigned char blue[] = {0,0,255};    
    const unsigned char lblue[] = {0,0,192};    
    const unsigned char dblue[] = {0,0,128};

    for (double alpha = 0.5; !disp.is_closed() && !disp.is_keyQ() && !disp.is_keyESC(); ) 
    {
        for(int x=1; x<img.width()-1; x++)
        {
            for(int y=1; y<img.height()-1; y++)
            {        
                pw = img(x,y,0,0);
                mw = 0;
    
                for(i=-1; i<=1; i++)
                {
                    for(j=-1; j<=1; j++)
                    {
                        mw += img(x+i, y+j, 0, 0);
                    }
                }

                mw /= 9;
                neu = (int)((pw - (alpha*mw)) / (1.0-alpha));

                if(neu > 255)
                {
                    neu = 255;
                }
                else if(neu < 0)
                {
                    neu = 0;
                }
                visu[0](x,y,0,0) = neu;

                valR = visu[0](x,y,0,0);                    // Read the red component
                valG = visu[0](x,y,0,1);                    // Read the green component
                valB = visu[0](x,y,0,2);                    // Read the blue component (Z


                avg = (int)((valR + valG + valB)/3);            // Compute average pixel value.

                visu[0](x,y,0,0) = visu[0](x,y,0,1) = visu[0](x,y,0,2) = avg;    //Graubild                
                
            }
        } 

        visu[1].fill(0).draw_text(25,5,"Alpha",white,0,1,tsize).
            draw_text(35,450-tsize-5,"%.2f",white,0,1,tsize,alpha);
        visu[0].draw_line(img.width()-1,0,img.width()-1,img.height(),white,1);
    
        const int yb = (int)((450-tsize-25)-(alpha*(450-50-(2*tsize))));
    
        visu[1].draw_rectangle(38, 450-tsize-23, 62, tsize+23, lblue, 1).
        draw_rectangle(39, 450-tsize-24, 61, tsize+24, dblue, 1).draw_rectangle(40, 450-tsize-25, 60, yb, blue, 1);

    	// cout << "Mouse: " << disp.mouse_y() << endl;

        if ((disp.button()) && (disp.mouse_x()>=img.width() + 38) && (disp.mouse_x()<=img.width() + 62) && 
            (disp.mouse_y()>=tsize + 25) && (disp.mouse_y()<=450-tsize-25))
			
        {
			
			alpha = ((disp.mouse_y() - lowerOffset) / ((offsetMod*upperOffset -450)/100));	
			oldalpha = ((disp.mouse_y() -450 +25 +tsize) / ((50 +(2*tsize) -450)/100));
            alpha/= 100;
	 oldalpha /= 100;
			
	 if(alpha>=0.999)
            {
                alpha = 0.999;
            }

	 if(oldalpha>=0.999)
            {
                oldalpha = 0.999;
            }
            cout << "alpha: " << alpha << endl;
	cout << "oldalpha: " << oldalpha << endl;
        }

        disp.resize(disp,false).display(visu).wait();
    }
}
redfalcon ist offline   Mit Zitat antworten
Für diesen Beitrag bedankt sich:
kanonenfutter (26.09.2010)
Alt 26.09.2010, 13:46   #5 (permalink)
Extrem Tweaker
 
Benutzerbild von kanonenfutter
 

Registriert seit: 10.07.2006
Beiträge: 2.290

kanonenfutter ist ein Lichtblickkanonenfutter ist ein Lichtblickkanonenfutter ist ein Lichtblickkanonenfutter ist ein Lichtblickkanonenfutter ist ein Lichtblick

Standard AW: [C++] Problem bei Denkaufgabe

Hm, sehr einfach, dennoch genial

Also ich versteh zwar nicht warum, wenn ich den Offset in Variablen packe, das ganze besser funzt als wenn ichs später berechne, aber naja..

Dickes Danke erstmal
kanonenfutter ist offline   Mit Zitat antworten
Alt 26.09.2010, 15:19   #6 (permalink)
Extrem Tweaker
 
Benutzerbild von kanonenfutter
 

Registriert seit: 10.07.2006
Beiträge: 2.290

kanonenfutter ist ein Lichtblickkanonenfutter ist ein Lichtblickkanonenfutter ist ein Lichtblickkanonenfutter ist ein Lichtblickkanonenfutter ist ein Lichtblick

Standard AW: [C++] Problem bei Denkaufgabe

Also das Teilprogramm läuft 1A, danke nochmal dafür

Nun wollte ich die gleiche Idee des einstellbaren Wertes mittels Schieberegler bei einem anderen Teilprogramm verwenden. Dabei geht es um die Binarisierung eines Bildes, heißt die Darstellung des Bildes nur mithilfe von schwarzen oder weißen Pixeln. Von einem s/w-Bild werden dabei die Grauwerte jeden Pixels ausgelesen und dann mit einem Schwellwert verglichen. Liegt der Pixelwert darunter wird er auf 0, darüber auf 255 gesetzt. Diesen Schwellwert würde ich ebenfalls gern mit einem solchen Balken einstellen. Einzige Umstellung ist, dass der Wert nun nicht von 0 bis 1 sondern von 0 bis 255 läuft (integer).

Gut, eigentlich kein Problem, habe die Idee von oben genommen, etwas abgeändert und, naja, habe mal wieder ein problem...

Mal abgesehen davon das ich mal wieder noch nicht sicher bin wie ich den Wert über die y-Mauposition errechnen soll, habe ich das Problem, dass mein Balken nicht ordentlich gezeichnet wird. Meiner Meinung nach müsste die Formel im Code richtig sein, nur scheint mir das Programm dort einige Klammern zu unterschlagen, und zeigt somit den Balken immer bei Position 0 an (für gwin = Grauwertschwelle = 0 bis 254), ab 255 wird der balken voll bis nach oben gezeichnet. Heißt für die Berechnung von 1 bis 254 läuft irgendwas schief...

Hier direkt mal der aktuelle Quelltext dazu:

Code:
#include "CImg.h"
using namespace cimg_library;

int main()
{
    CImg<int>img("lena.jpg");
    CImg<int>gimg(img.width(), img.height(), 1, 3, 0);
    CImg<int>bimg(img.width(), img.height(), 1, 3, 0);
    CImgList<double>visu(bimg, CImg<int>(100,600,1,3,0));
    CImgDisplay disp(visu,"Test");
    //disp.resize(disp.screen_width()-20, 600*(disp.screen_width()-20)/1700, false);
    
    int valR, valG, valB = 0;
    double avg = 0.0;
    int tsize = 24;
    double upperOffset = tsize+25;
    double lowerOffset = 600-tsize-25;
    double offsetMod =  2;

    const unsigned char white[] = {255,255,255};    
    const unsigned char blue[] = {0,0,255};    
    const unsigned char lblue[] = {0,0,192};    
    const unsigned char dblue[] = {0,0,128};

    for (int gwin = 128; !disp.is_closed() && !disp.is_keyQ() && !disp.is_keyESC(); ) 
    {
        for(int x = 0; x < img.width(); x++)        //Schleife über x,y und Farbkanal
        {
            for(int y = 0; y < img.height(); y++)
            {
                valR = img(x,y,0,0);                    // Read the red component
                valG = img(x,y,0,1);                    // Read the green component
                valB = img(x,y,0,2);                    // Read the blue component (Z-coordinate omitted here).
                avg = (valR + valG + valB)/3;            // Compute average pixel value.

                gimg(x,y,0,0) = gimg(x,y,0,1) = gimg(x,y,0,2) = avg;    //Graubild
                
                if(avg>=gwin)            //Binarisierung
                {
                    visu[0](x,y,0) = visu[0](x,y,1) = visu[0](x,y,2) = 255;
                }
                else visu[0](x,y,0) = visu[0](x,y,1) = visu[0](x,y,2) = 0;
            }
        }

        visu[1].fill(0).draw_text(18,5,"Grenze",white,0,1,tsize).
            draw_text(36,600-tsize-5,"%d",white,0,1,tsize,gwin);
        visu[0].draw_line(img.width()-1,0,img.width()-1,img.height(),white,1);
    
        double pro = gwin / 255;
        const int yb = (int)(lowerOffset-(pro*(600-offsetMod*upperOffset)));        // ???
    
        visu[1].draw_rectangle(38, 600-tsize-23, 62, tsize+23, lblue, 1).
        draw_rectangle(39, 600-tsize-24, 61, tsize+24, dblue, 1).draw_rectangle(40, 600-tsize-25, 60, yb, blue, 1);
    
        if ((disp.button()) && (disp.mouse_x()>=img.width() + 38) && (disp.mouse_x()<=img.width() + 62) && 
            (disp.mouse_y()>=tsize + 25) && (disp.mouse_y()<=600-tsize-25))
        {
            gwin = (int)(600 -disp.mouse_y() -(tsize+25));        // ???

            if(gwin>255)
            {
                gwin = 255;
            }
        }

        disp.resize(disp,false).display(visu).wait();
    }
}
Und hier noch ein Bildchen zur Veranschaulichung:

http://www.tweakpc.de/forum/members/...e1642-c-bv.jpg

Bin nochmal am tüfteln, wenn jmd eine Idee hat, nur her damit

mfg
kanonenfutter ist offline   Mit Zitat antworten
Alt 27.09.2010, 10:50   #7 (permalink)
Extrem Tweaker
 
Benutzerbild von kanonenfutter
 

Registriert seit: 10.07.2006
Beiträge: 2.290

kanonenfutter ist ein Lichtblickkanonenfutter ist ein Lichtblickkanonenfutter ist ein Lichtblickkanonenfutter ist ein Lichtblickkanonenfutter ist ein Lichtblick

Standard AW: [C++] Problem bei Denkaufgabe

Ok hat sich bereits erledigt, hier dann mal die geänderten Programmzeilen aus dem Code oben, so dass es funzt:

Code:
const int yb = (int)(LowerOffset-((gwin/255)*(gimg.height()-OffsetMod*UpperOffset)));
    
        visu[1].draw_rectangle(38, gimg.height()-tsize-23, 62, tsize+23, lblue, 1).
        draw_rectangle(39, gimg.height()-tsize-24, 61, tsize+24, dblue, 1).draw_rectangle(40, gimg.height()-tsize-25, 60, yb, blue, 1);
    
        if ((disp.button()) && (disp.mouse_x()>=gimg.width() + 38) && (disp.mouse_x()<=gimg.width() + 62) && 
            (disp.mouse_y()>=tsize + 25) && (disp.mouse_y()<=gimg.height()-tsize-25))
        {
            gwin = 255 * ((disp.mouse_y() - LowerOffset) / (OffsetMod*UpperOffset -gimg.height()));

            if(gwin>255)
            {
                gwin = 255;
            }
        }
PS: gwin war zuvor ein int, dadurch konnte die Berechnung gwin/255 nicht durchgeführt werden und war somit immer 0, außer für gwin = 255, da war es dann eben 1. Also den auf double und dann läufts schon besser

mfg

Geändert von kanonenfutter (27.09.2010 um 11:10 Uhr)
kanonenfutter ist offline   Mit Zitat antworten
Antwort

Stichworte
denkaufgabe, problem


Aktive Benutzer in diesem Thema: 1 (Registrierte Benutzer: 0, Gäste: 1)
 
Themen-Optionen
Ansicht

Forumregeln
Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist aus.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are an


Ähnliche Themen
Thema Autor Forum Antworten Letzter Beitrag
Eine kleine Denkaufgabe (Portal) VL Off Topic 8 06.09.2010 16:29
Denkaufgabe - Lösung gesucht Jim Phelps Off Topic 19 05.11.2005 19:56
[Problem] Ultra DMA 100 Problem ! Gordon Gekko RAM Arbeitsspeicher 1 08.12.2002 14:47
AMD Athlon xp Problem + G4600 VDT MSI Problem Gast AMD: CPUs und Mainboards 0 22.11.2002 13:25


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:45 Uhr.






Powered by vBulletin® Version 3.8.10 (Deutsch)
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
SEO by vBSEO 3.5.2 ©2010, Crawlability, Inc.
Impressum, Datenschutz Copyright © 1999-2015 TweakPC, Alle Rechte vorbehalten, all rights reserved