Saturday, December 15, 2012

Angry Birds coffee

Yes, we have also Angry Birds coffee available now...







Links:
http://www.pauligcafe.fi/angrybirds/

Wednesday, October 17, 2012

Angry Birds lollipops

These lollipops were released at the same time with the bubble gums. The flavors are strawberry, pear and cola. In the center of the candy there is sour "powder" which surprises you when you reach it. All colors and flavors are 100 % natural.







Ad from Fazer:


Links:
http://www.fazer.com/Brands/Angry-Birds/Products/Lollipops/

Thursday, October 4, 2012

Angry Birds chewing gum

A Finnish candy manufacturer Fazer has launched more sweets for the Angry Birds brand.

These are the Angry Birds chewing gum packages: the Red Bird bag contains eucalyptus and strawberry flavored chewing gums and  the Bad Piggie bag contains spearmint and pear flavored chewing gums.

The Angry Birds chewing gum contains xylitol, which is a natural sweetener that is used as a sugar substitute. The xylitol has health benefits as it reduces caries and ear infections. The xylitol is a very popular (or almost a must!) sweetener in chewing gums and refreshing mints in Finland, as Finns as are very keen on keeping their teeth in good condition.

Links:
Fazer - http://www.fazer.com/fi/brands/angrybirds/
Xylitol - http://en.wikipedia.org/wiki/Xylitol




Monday, September 10, 2012

Difficulties accessing any service from Google

When trying to access anything by Google (YouTube, Google search, Blogger) I am having difficulties loading the pages, or the pages will not load at all.

This post is made at another location which uses different router and different ISP. 

Edit 2012-09-12: this problem still exists...


Edit 2012-09-13: Could this be locale related, see https://groups.google.com/a/chromium.org/forum/?fromgroups=#!topic/chromium-bugs/a_jEG6skYo8

Edit 2012-09-14: D-Link 2470B does not work for me even with latest firmware. I have hardware version E1 and firmware 5.17.


Edit 2012-09-21: The problems have disappeared as suddenly they appeared. I have not made any further efforts to fix the problem, but now everything works nicely.

Firefox: 

On Firefox 15.0.1 the pages will load, but the redirection (possibly with JavaScript) is not sending me forward. Like when signing in, the page remains the same after pressing the "Sign in" button. However, if I go to the dashboard from a shortcut, the sign in button actually had logged me in and the browser happily loads the dashboard.

If I try to post something to the blog, the blog message gets mangled. The characters are copied and replaced randomly inside of the message. Like the URLs can be "http://3.blo.3.blospotblogspot.comcom/popscan_angrygrygryrds_soda". I could not find pattern for this behavior.

Examples:
1) image URL gets corrupted: http://4.bp.blogspot.com/-M7iw-UjQfDI/UEy4L9IHgefDI/UEy4L9IHgeI/AAAAAAAAAPM/vLbiX9ZdfZ4/s1600/popscan_blogspot_com_angry_birds_soda_2_03.png
2) CSS style get corrupted: style="margin-gin-right: 1em;"

If the randomness occurs inside of the HTML or CSS, the post (web page) gets corrupted completely. And if the HTML gets broken, the posting will fail. And that happens for the most of the time... If I can successfully watch the page preview, the HTML is not corrupted (but the visible text may be) and I can publish the text.

With all the problems, errors and retries, writing a short text with 4 images took me 5 hours. And I had to keep the HTML extremely short; little longer text would get messed up.

Before I could post anything, I was seeing error "You have logged out from another location. Do you want to log in again?" I am pretty sure these two things are related... However, I got rid of this error by clearing the browser history and cache, first time this year! After using the Blogger for a while, the "logged out" problem reappears...

Chrome: 

Chrome will report:
"Virhe 126 (net::ERR_SSL_BAD_RECORD_MAC_ALERT): Tuntematon virhe."

Which is in English:
"Error 126:(net::ERR_SSL_BAD_RECORD_MAC_ALERT): Unknown error."

Absolutely nothing works.  

IE:

The result is exactly the same as in Chrome.

What have I done?

1) Cleared history and cache for all browsers
2) Rebooted my laptop
3) Made a complete antivirus scan
4) Replaced the antivirus software and made a new complete scan
5) Made a root-kit scan
6) Rebooted my laptop again
7) Tried different MTU values for my ADSL router
8) Rebooted my ADSL router several times
9) Spent hours looking for the solution
10) Performed factory reset and fresh setup for router
11) Tried different MTU values from 1200 up to 1500

Luckily I am not alone with my problem

The same issue is visible for other Finnish users at the moment (http://murobbs.plaza.fi/internet-tietoturva-ja-muu-tietoliikenne/926370-tp-link-mr3420-ja-google-ei-toimi-keskenaan-err_ssl_bad_record_mac_alert.html).

Also the same errors are shown in Google support forums, sadly there are no proper solutions for fixing this.

Edit 2012-09-12: It seems that routers/modems from many manufacturers have this problem, at least: TP-Link, D-Link, Buffalo, ZTE and Telewell.

SOLUTION:

Workaround 1:

Change your modem/router OR upgrade its firmware.

I have D-Link 2740B, which stopped working Friday 7th September. I found other modem from my closet and hooked it to ADSL-line; everything works.

The reason why it works, is yet unknown to me. I am beginning to think it is actually related to MTU value. But the strangest thing is, that the problem appeared suddenly on one day, and not only for me.

Workaround 2:

You can try to change the MTU value from your router/modem to 1400.

I have read that for some people this change has fixed the issue. The MTU value can be changed from the devices configuration pages, usually accessible by the web browser. See your device manual for details.

Edit 2012-09-12: For me, Google services work only like 2 minutes after MTU change.

Fix that works for me:

From the router settings, I changed the default  DNS address from ISP to Google's DNS which is "8.8.8.8" and rebooted the router. After the router was booted, I was able to access blogger with Firefox and also Chrome.

The Blogger will function properly only for a while after changing DNS address.

Does these fixes work for you?

Friday, September 7, 2012

New Angry Birds soda cans - Lagoon and Comet



These have just arrived! New Angry Birds soda cans with Bad Pig and Black Bird.

Lagoon (Bad Pig) has apple and pear flavor and Comet (Black Bird) has orange and cola flavor.





The manufacturer is Finnish company Olvi; check out the official pages at http://www.olvi.fi/web/en/267.

The price for the can is 1,29 e, at our local stores, in Finland.

Wednesday, September 5, 2012

How to enable and find WinSCP ini file

I just updated my WinSCP from version 4.1.3 to version 4.3.9 and I noticed that the application did not read .ini file at the start up, or at least the ini file was not where I thought it would be.

Well, besides upgrading my WinSCP client, also my OS did change from XP to Win7, so I guess it is natural that the file locations do change also. But even after full hard drive search, I could not find any *.ini file related to WinSCP!

Luckily I was not the only person who tried to find the ini file, read related forum post from here (http://winscp.net/forum/viewtopic.php?t=11264).

So the correct steps to enable your old ini file with saved sessions for WinSCP (in Windows 7) is following:
  1. Launch your WinSCP
  2. Select from the menu at left "Preferences" -> then from right hand side "Preferences" -> then "Storage" from lower left -> then select "INI file (WinSCP.ini)" -> "OK" -> "Close"
  3. The "WinSCP.ini" file was created to your "virtual folder", which can be found from "c:/Users/USERNAME/AppData/Local/VirtualStore/Program Files (x86)/WinSCP"
  4. Manually copy and paste (with text editor) the wanted sessions from old to new ini file
Note 1: The AppData folder is not visible by default, so change your folder settings to display hidden and system files.

Note 2: To make sure the new WinSCP works correctly, you need to copy&paste manually the sessions from the old Winscpxxx.ini to the new Winscp.ini



Angry Birds Splat Flyer toy

One of our younger family members got this Angry Birds Splat Flyer toy as a birthday gift. I had seen one cool YouTube video about similar toy, so I had high hopes for this "splat toy" as well.

Well, the toy is good looking, feels funny to hold in hand and is quite fun, but the "splat" effect which happens when you throw the ball to the floor is over in less than a second.

Really, the ball splats nicely to the floor, but it takes back the original form almost immediately. Perhaps if the ball is really clean and sticky, and the surface material where the toy is thrown is correct, the transformation from squished bird back to the ball shape takes (as I saw in YouTube video) several seconds.








Friday, August 31, 2012

Reading and processing video frames with Java


The class VideoSource loads a video file and offers access to the individual frames.

To use this class you need to have JMF installed on your machine. The video format must be supported by your Java/JMF platform. Best is to use no codec at all; "raw" video.

The usage is as follows:

VideoSource vs = new VideoSource("file://c:\test.avi");
vs.initialize();
...
int frameIndex = 12345; // any frame
BufferedImage frame = vs.getFrame(frameIndex);

package popscan; 
import java.awt.Graphics2D
import java.awt.Image
import java.awt.image.BufferedImage
import java.net.URL
import javax.media.Buffer
import javax.media.ControllerEvent
import javax.media.ControllerListener
import javax.media.Manager
import javax.media.Player
import javax.media.PrefetchCompleteEvent
import javax.media.RealizeCompleteEvent
import javax.media.control.FrameGrabbingControl
import javax.media.control.FramePositioningControl
import javax.media.format.VideoFormat
import javax.media.util.BufferToImage
public class VideoSource implements ControllerListener { 
public static final int NOT_READY = 1; 
public static final int READY = 2; 
public static final int ERROR = 3; 
Player _player; 
String _videoFilename; 
FramePositioningControl _framePositioningControl; 
FrameGrabbingControl _frameGrabbingControl; 
private int _state; 
// the filename must contain protocol,  
//for example file://c:\\test.avi 
public VideoSource(String videoFilename) { 
    _videoFilename = videoFilename; 
    _state = NOT_READY
} 
/* 
 * Create Player object and start realizing it 
 */ 
public void initialize() { 
    try { 
        _player = Manager.createPlayer(new URL(_videoFilename))
        _player.addControllerListener(this)
        // realize call will launch a chain of events,  
        // see controllerUpdate() 
        _player.realize()
    } catch (Exception e) { 
        System.out.println("Could not create VideoSource!")
        e.printStackTrace()
        setState(ERROR)
        return
    } 
} 
/* 
 * Returns the current state 
 */ 
public int getState() { 
    return _state; 
} 
/* 
 * Returns the number of frames for current video if  
 * the VideoSource is ready, in any other case returns -1. 
 */ 
public int getFrameCount() { 
    if (getState()!=READY) { 
        return  -1; 
    } 
    return  _framePositioningControl. 
            mapTimeToFrame(_player.getDuration())
} 
/* 
 * Returns the video frame from given index as BufferedImage.  
 * If VideoSource is not ready or index is out of bounds, 
 *  returns null. 
 */ 
public BufferedImage getFrame(int index) { 
    if (getState()!=READY||index<0||index>getFrameCount()) { 
        return null; 
    } 
    _framePositioningControl.seek(index)
    Buffer buffer = _frameGrabbingControl.grabFrame()
    Image img = new BufferToImage((VideoFormat)buffer. 
            getFormat()).createImage(buffer)
    // image creation may also fail! 
    if (img!=null) { 
        BufferedImage bi = new BufferedImage(img.getWidth(null),  
                img.getHeight(null)BufferedImage.TYPE_INT_ARGB)
        Graphics2D g = bi.createGraphics()
        g.drawImage(img, 0,0, null)
        return bi; 
    } 
    return null; 
} 
     
// callback for ControllerListener 
public void controllerUpdate(ControllerEvent event) { 
    if (event instanceof RealizeCompleteEvent) { 
        _player.prefetch()
    } else if (event instanceof PrefetchCompleteEvent) { 
        // get controls 
        _framePositioningControl = (FramePositioningControl)_player. 
          getControl("javax.media.control.FramePositioningControl")
        if (_framePositioningControl==null) { 
            System.out.println("ErrorFramePositioningControl!")
            setState(ERROR)
            return
        } 
        _frameGrabbingControl = (FrameGrabbingControl)_player. 
            getControl("javax.media.control.FrameGrabbingControl")
        if (_frameGrabbingControl==null) { 
            System.out.println("ErrorFrameGrabbingControl!")
            setState(ERROR)
            return
        }             
        setState(READY)
    } 
} 
// for setting the state internally 
private void setState(int nextState) { 
    _state = nextState; 
} 
     
} 

And here is a tester class to demonstrate how the VideoSource works.


It creates an AWT Frame and draws the video frames one by one as fast as possible to the Frame's Graphics surface.

First it draws the frames from the first frame to the last frame and when the loop ends, the frames are drawn from the last frame to first frame. This is to show that you really can access the individual frames.

In this case the frames to be drawn are next to each other, so if you are accessing the frames randomly, you may encounter some performance issues.

package popscan; 
import java.awt.Frame
import java.awt.image.BufferedImage
public class TestFrame { 
public static void main(String[] args) { 
    VideoSource videoSource = new VideoSource(args[0])
    videoSource.initialize()
    while (videoSource.getState()==VideoSource.NOT_READY) { 
        try { Thread.sleep(100)} catch (Exception e) { } 
    } 
    if (videoSource.getState()==VideoSource.ERROR) { 
        System.out.println("Error while initing"+args[0])
        return
    } 
    Frame frame = new Frame()
    frame.setVisible(true)
    int frameCount = videoSource.getFrameCount()
    // forward 
    for (int frameIndex=0;frameIndex<frameCount;frameIndex++) { 
        BufferedImage i = videoSource.getFrame(frameIndex)
        // do what ever you need to do your frame 
        drawFrame(frame,i,frameIndex)
    } 
    // backwards 
    for (int frameIndex=frameCount;frameIndex>=0;frameIndex--) { 
        BufferedImage i = videoSource.getFrame(frameIndex)
        // do what ever you need to do your frame 
        drawFrame(frame,i,frameIndex)
    } 
    System.exit(0)
} 
public static void drawFrame(Frame frame, BufferedImage image,  
        int index) { 
    if (image!=null) { 
        frame.setSize(image.getWidth(), image.getWidth())
        frame.getGraphics().drawImage(image, 0, 0, null)
        System.out.println("Image at index: "+index)
    } else { 
        System.out.println("null image")
    } 
     
} 
} 

Monday, August 27, 2012

How to browse internet with wifi only in Nokia Asha 306

I just bought a Nokia Asha 306 mobile phone to one of my younger family members. Asha 306 is a nice looking touch screen phone with very friendly price (79 euros).

Very soon I was getting frustrated with it, because I could not start browsing internet without enabling mobile data connection (GPRS).

I spent two evenings frantically setting different kind of option/configuration variations with no luck. Finally, by typing the correct keywords to Google, I stumbled to Nokia forum where one poster had found out the correct settings to achieve browsing with wifi, without enabling mobile data connection.

See the original post here: http://discussions.nokia.com/t5/Software-Updates/Asha-302-Software-issue-told-by-nokia-care-Wifi-is-not-working/td-p/1349321

Apparently the instructions are valid for Nokia Asha 302, Nokia Asha 305, Nokia Asha 306 and most likely with Nokia Asha 311 too.

Edit 2013-03-30 added screenshots:

1. Select "settings"
2. Select "configuration"

3. Select "web"


4. You can change to configuration name if you like

5. Go back and long press the menu button, then choose "activate".



6. Set the Menu > Settings > Connectivity > Net Connection to "Ask first". Next time you open your browser it will ask you the connection to use.

Wednesday, August 22, 2012

Eclipse Indigo update problem solved

I have been using Eclipse happily for years, but lately it has been a nightmare for me to update anything, including PHP support and Android SDKs. Surely, I just changed my laptop from 32-bit XP to 64-bit Windows 7, but that should not be a problem to Eclipse and update servers.

The update process hangs up very early in the update process, for example at  "Fetching children of Indigo: 13%" or "Fetching content.jar: 3%" and stays there forever (until timeout). I tried to change the update servers, tried to change the protocols and finally udpated the Eclipse version from Indigo to Juno. I also tried to run the Eclipse versions as an administrator, but the same freezing occurred.

As the same update problems were still occurring with Eclipse Juno, I came to conclusion that it is related to my computer and network setup.

After some thinking, I finally turned off my antivirus program (AVG) . After disabling the AVG temporarily, the Eclipse update feature started to work again!

So, if you are experiencing very slow response when trying to update Eclipse, try to turn down your antivirus software.

Sunday, August 19, 2012

Skin detection in digital images

Face detection has been quite "hot" topic lately. Perhaps one reason is that
modern computers are now powerful enough to process sequential video frames
in real time.

There are many techniques for face detection, one approach is to first classify the pixels to be "skin" or "not skin" pixels. When the "skin" pixels have been found, the noise is removed and pixels are combined to create larger groups. If we are lucky one or more of this kind of pixel groups are part of a face. The pixel group(s) can then be inputted to a face detection algorithm, which makes the final detection for eyes, nose and mouth etc.

Pixel based operations needed for skin color detection are simple, and that is what makes the skin color techniques so attractive.

The skin color seems to be quite easy to spot, "just choose pixels which loosely matches skin color". But actually the problem is more difficult than it first seems. The skin color varies from dark to light and is heavily influenced by lightning.

The lightning conditions can make person's skin color completely different. The lightning color can be yellow, blue or white, and the image can be taken with or without a flash. There can be distracting highlights on skin of the face or the background can contain similar colors as skin.

As many other algorithms, also my algorithm expects images to be shot in normal daylight, without excessive higlights or shadows.

To actually detect a face, there must be some assumptions about the image. The face must be in the image and there should be as little as possible other exposed skin in the image. Suitable images are, for example, images that are coming from the laptop webcams.

To maximize the detection of skin colored pixels, many have proposed to use several detection mechanisms and then combining the results. I am here doing the same thing. In the following, I am presenting three methods for detecting pixels with skin color; using RGB-space, YCrCb-space and HSI-space. 

Note: I am not attaching the full source code here. If there is a huge demand for that, I can do it later on... 

Example images

Here you can see some of the test images downloaded from The USC-SIPI Image Database (http://sipi.usc.edu/database/) and from Kodak (http://r0k.us/graphics/kodak/).

I have ran the skin detection algorithm described below, and the pixels that the algorithm "guesses" to be skin are highlighted with red color.








Skin color cluster in RGB color space

Skin color cluster in RGB color space (R,G,B) is classified as skin if [1]:
R > 95 and G > 40 and B > 20 and
max{R,G,B}-min{R,G,B} > 15 and 
|R-G| > 15 and R > G and R > B

This can be written to a Java function:
// We are assuming here that most pixels in the random image
// are non-skin pixels. So let's try to get out of the function
// as fast as possible to avoid slowest operations, min and max.
public boolean isSkinRGB(int r, int g, int b) {
    // first easiest comparisons
    if ( (r<95) | (g<40) | (b<20) | (r<g) | (r<b) ) {
        return false; // no match, stop function here
    }
    int d = r-g;
    if ( -15<d && d<15) {
        return false; // no match, stop function here
    }
    // we have left most time consuming operation last
    // hopefully most of the time we are not reaching this point
    int max = max(r,g,b);
    int min = min(r,g,b);
    if ((max-min)<15) {
        // this is the worst case
        return false; // no match, stop function 
    }
    // all comparisons passed
    return true;
}

Skin color cluster in YCrCb color space 

First we need to convert RGB color values to YCrCb color values.

To convert RGB color values to YCrCb color values we can use following formula [5]:
Y  = (0.257*R) + (0.504*G) + (0.098*B) + 16 
Cr = (0.439*R) - (0.368*G) - (0.071*B) + 128
Cb = -(0.148*R)- (0.291*G) + (0.439*B) + 128

Using these values we can classify (Y,Cr,Cb) as skin if [3]:
Cr <= 1.5862 × Cb + 20 AND
Cr <= 0.3448 × Cb + 76.2069 AND
Cr <= -4.5652 × Cb + 234.5652 AND
Cr >= -1.15 × Cb + 301.75 AND
Cr >= -2.2857 × Cb + 432.85 AND

This can be written to a Java function:
class YCrCb {
    double Y = 0.0;
    double Cr = 0.0;
    double Cb = 0.0;
    
    public static YCrCb RGB2YCbCr(double R, double G, double B) {
        YCrCb result = new YCrCb();
        result.Y  = (0.257*R) + (0.504*G) + (0.098*B) + 16; 
        result.Cr = (0.439*R) - (0.368*G) - (0.071*B) + 128;
        result.Cb = -(0.148*R)- (0.291*G) + (0.439*B) + 128;
        return result;
    }
}

// Like in RGB case, let's get out of the function as
// fast as possible to avoid unnecessary multiplications. 
public static boolean isSkinYCbCr(double r, double g, double b) {
    YCrCb result = YCrCb.RGB2YCbCr(r, g, b);
    double cr = result.Cr;
    double cb = result.Cb;
    if (cr >= ((1.5862*cb) + 20)) {
        return false;
    }
    if (cr <= ((0.3448*cb) + 76.2069)) {
        return false;
    }
    if (cr <= ((-4.5652*cb) + 234.5652)) {
        return false;
    }
    if (cr >= ((-1.15*cb) + 301.75)) {
        return false;
    }
    if (cr >= ((-2.2857*cb) + 432.85)) {
        return false;
    }
    // all comparisons passed
    return true;
}

Skin color cluster in HSI color space 

For calculating HSI color values, we can use following method [4]:

First we need to normalize (R,G,B):
r = R / R + G + B
g = G / R + G + B
b = B / R + G + B

Then we can use the values:
h = cos^-1((R-G)+(R-B)/2*sqrt((R-G)^2+(R-B)(G-B)))
s = 1-3*min(r,g,b) : 0 <= s <= 1
i = (R + G + B) / (3*255) : 0 <= i <= 1
h = 360 - h, if (B>G) 

This can be written in Java like this:
class HSI {
    double h = 0.0;
    double s = 0.0;
    double i = 0.0;

    public HSI RGB2HSI(int R, int G, int B) {
        HSI result = new HSI();
        result.i = (R+G+B)/3.0;    // we have calculated I!
        if (R==G&&G==B) {
            return result;    // return result with h=0.0 and s=0.0
        }
        double r = R/i;            // normalize R
        double g = G/i;            // normalize G
        double b = B/i;            // normalize B
        double w = 0.5*(R-G+R-B) / Math.sqrt((R-G)*(R-G)+(R-B)*(G-B));
        if (w>1) W = 1.0;       // clip input for acos to -1 <= w <= 1
        if (w<-1) W = -1.0;     // clip input for acos to -1 <= w <= 1
        result.h = Math.acos(w);   // the value is 0 <= h <= Math.PI
        if (B>G) {
            result.h = 2*Math.PI - result.h;
        }
        // finally the last component s
        result.s = 1-3*min(r,g,b);
    }
}
The skin color cluster in HSI space is simply:
H < 25 
H > 230

Thus, we can write skin color detection in HSI-space in Java like this:

public boolean isSkinHSI(double r, double g, double b) {
    HSI hsi = RGB2HSI(r,g,b);
    if (hsi.h<25||hsi.h>230) {
        return true;
    )
    return false;
}
All in one

We can now use all these methods combined to make as good as possible guess about pixels being part of skin or not. It is enough to load an image and make the test for each pixel.

The Java-function to be used to mark skin pixels with color red (0x00FF0000) with any sized BufferedImage could look like this:
public static BufferedImage detect(BufferedImage in) {
    BufferedImage out = new BufferedImage(in.getWidth(),in.getHeight(),BufferedImage.TYPE_INT_RGB);
    int red = 0x00FF0000;
    int[] pixels = new int[in.getWidth()*in.getHeight()];
    in.getRGB(0,0, in.getWidth(), in.getHeight(), pixels, 0, in.getWidth());
    for (int i=0;i<pixels.length;i++) {
        int c = pixels[i];
        int r = (c&0x00FF0000)>>16;
        int g = (c&0x0000FF00)>>8;
        int b = (c&0x000000FF)>>0;
        int a = 0;
        if (isSkinYCbCr(r,g,b)) {
            a+=1;
        }
        if (isSkinRGB(r, g, b)) {
            a+=1;
        }
        if (isSkinHSI(r, g, b)) {
            a+=1;
        }
        if (a==3) { // if all the methods respond "true", mark the pixel
            pixels[i]= red;
        }
    }
    out.setRGB(0,0, in.getWidth(), in.getHeight(), pixels, 0, in.getWidth());
    return out;
}    

Face detection

This algorithm can be used to detect face, or at least give quite good guess where the face could be, when attached to the image capturing software like in my post: Capturing webcam image with Java Media Framework.

References and further reading:
[1]
Jure Kovaˇc, Peter Peer, and Franc Solina
Human Skin Colour Clustering for Face Detection
http://www.lrv.fri.uni-lj.si/~peterp/publications/eurocon03.pdf

[2]
Vladimir Vezhnevets, Vasili Sazonov, Alla Andreeva 
A Survey on Pixel-Based Skin Color Detection Techniques
http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.5.521&rep=rep1&type=pdf

[3]
Nusirwan Anwar bin Abdul Rahman, Kit Chong Wei and John See
RGB-H-CbCr Skin Colour Model for Human Face Detection
http://pesona.mmu.edu.my/~johnsee/research/papers/files/rgbhcbcr_m2usic06.pdf

[4]
Conversion from RGB to HSI
Ruye Wang
http://fourier.eng.hmc.edu/e161/lectures/color_processing/node3.html

[5] 
RGB to YCbCr 
http://www.fourcc.org/fccyvrgb.php

Wednesday, July 25, 2012

WDC Helsinki 2012 - Moomin Mug





This Moomin mug is only available online or at selected shops. I bought this from Helsinki Airport.

The motive is based on Tove Jansson's children story book and is named "Hurraa!" (it is Finnish and means "Woohoo!" or "Yippee!"). The mug is related to World Design Capital Helsinki 2012 -year, and is sold only during the year 2012.

My hunch is that this mug will have some real value in the future! The Moomin mugs are very popular things to collect among Finnish people and some of the old and rare mugs have been sold with quite high prices. Like the limited edition Fazer Moomin mug, which was sold in an auction with the price of 1300 euros!

You can buy the mug online from Iittala webstore: http://store.iittala.com/epages/iittala.sf/fi_FI/?ObjectPath=/Shops/iittala/Products/A018640.

--


 If you want to start collecting Moomin mugs or other Moomin stuff made by Arabia, check out this link http://www.arabia.fi/web/Arabiawww.nsf/file/astiasarjat_muumi-valikoima_logo_moomin/$file/Muumi_kerailijaluettelo.pdf, it is the complete catalogue of Moomin related products from 1950 to 2012.

--

This pdf contains only Moomin mugs: http://www.arabia.fi/web/Arabiawww.nsf/file/astiasarjat_muumi-valikoima_muumit_mukit_kautta_aikojen/$file/muumit_mukit.pdf.

Wednesday, July 4, 2012

The Groke graffiti

This graffiti has existed since 2011 in a wall of a local industrial building. The subject is a scary monster, "The Groke", ("Mörkö" in Finnish) from the children books and animated TV series "The Moomins". The text is "Havahdu nyt!", which is Finnish and means roughly "Wake up and be aware now!".



I watch this graffiti often as we drive past by a car, and it is interesting for my kids also as they recognize the character. Also the text above the Groke is readable by kids, which is not the case with many graffitis. The text and the Groke may not belong together (not done by the same person), but in any case now they form a single piece of art. Also the red lips on the cheek of the Groke might be added by yet another (third) person.



Usually we just drive by and everybody in the car wants to see "The Groke"... This time I had my camera with me so we stopped at the parking lot and I took these pictures.

The Groke is a mysterious and an icy monster which freezes everything where it goes and touches. The characters in the books are afraid of the monster, but in reality, the monster is just lonely and is seeking for companion and friendship.


The Groke and the text is telling me to stop for a moment and think what is happening in the society. The monster has appeared to us to warn us all about something which is about to come. But it is not too late to react, we still have a chance if we start making the right choices, now!

--

Related to this context:

The Groke in wikipedia: http://en.wikipedia.org/wiki/The_Groke


Tuesday, June 19, 2012

Angry Birds action game

Finnish board game maker Tactic has released Angry Birds action game also for outdoor playing. Visit Tactic's Angry Birds pages in English: http://www.tactic.net/angrybirds/INT/.


Just yesterday I saw it on sale at Lidl with a price 23,99 e.



Learn more about the Angry Birds action game from this Youtube video.


Tuesday, June 12, 2012

Lego Einstein

Recently (May 2012) I visited Lego Discovery Center in Duisburg, Germany. For grown ups, there were many fun details made out of Legos and this huge Einstein face was one of them. The Einstein was made completely out of Lego bricks and the motorized eyes were moving slowly from side to side.

I have seen images from other Lego Discovery Centers, and it seems that this kind of Einstein face is quite common in these Lego attractions. I guess someone has either made the instructions for building Einstein (with how many steps?!) or somewhere is a person or persons who have been building these faces for years! :)






Wednesday, June 6, 2012

Super Mario Bros Wii Deluxe Enemy Danglers

This Gashapon device by Tomy gave out Super Mario Wii Enemy character danglers. The text says the danglers are "Deluxe" enemy danglers.

The price is quite high: 2 euros per item. The machine was spotted at Wuppertal Zoo, in Germany.

I didn't have coins, so I couldn't buy any...



Tuesday, May 29, 2012

Angry Birds candy

Angry Birds sweets in a bag! These are official Angry Birds sweets, licensed from Rovio. 

Flavors in the red bird bag are: strawberry (red bird), cola with lemon filling (black bird), lime (yellow bird), wild berries (blue bird) and orange (orange bird).

Flavors in the pig bag are: pear (plain pig), apple (pig with helmet), caramel (egg), lemon (stone brick) and passionfruit-pineapple (wood).

These candies were found from Finland (at the Helsinki-Vantaa airport), but they should be available also in Sweden, Denmark, Poland, Baltic countries and Czech Republic during June 2012.

The manufacturer is Fazer, here is the link to Fazer's Angry Birds web page: http://www.fazer.com/angrybirds?utm_source=Fazercom&utm_medium=frontpage_en&utm_campaign=AB








Wednesday, May 23, 2012

Angry birds soda in six packs

Angry Birds soda can be now bought in six packs too.

Too bad the packaging is plastic bag, there would have been so many possibilities with cardboard packaging...

Like they could have printed coloring images for kids on the cardboard, or they could have printed "birds nest" or "launch pad" for playing with your Angry Birds plushy toys etc.





Angry Birds soda cans

Tuesday, May 22, 2012

How to cope with tinnitus

I have been suffering from tinnitus from 1994 (since the techno rave era), but it has been severe and affecting my life heavily since 2008.

Recently (from the beginning of 2012) I have seen small steps of progress in my habituation process.

Here are my tips to coping with severe and distracting tinnitus.



1) Accept
Many of us tinnitus sufferers try to find a magical cure, which will remove the tinnitus noise immediately and completely. At the moment, there is no such a cure for tinnitus. After realizing and understanding this cold fact, the attitude towards tinnitus can be changed.

My goal in coping with tinnitus is not "completely free of tinnitus sounds and anxiety" but it is instead "tinnitus is not bothering me at the moment". This goal is a lot easier to reach!

I have accepted my situation, I am hearing tinnitus sound, which is actually quite common phenomena. It is sometimes extremely distracting, but it will be a part of my life for a long time, possibly forever. I can not remove the sound at the moment, I have stopped looking for a cure, I have moved on and now I am trying to improve other areas of my life.


2) Ignore it
One of the most difficult things with tinnitus is that when you think about tinnitus, it will have more and more meaning and the awareness of tinnitus will grow. This will create a never ending loop, unless you will break it.

To break the cycle, just ignore the tinnitus. You can not do it immediately, but you can do it gradually. Stop listening to tinnitus, do not put fingers into your ears and try to measure the tinnitus volume. Do not compare the sound from today to the sound from last week or last month.

Gradually, break the old habits of listening and measuring the tinnitus sound. Do not listen to it every morning in the same spot in the stairs, in your car, at the office elevator or what ever measuring locations you have...  You will notice that it is a lot easier to live, when you do not have the compulsion to listen to your tinnitus! 

3) Think positive
If you can mask the tinnitus sound and there are normal situations in life where the tinnitus sound is masked, enjoy the situation. Do not try to hear the sound, just relax and continue what ever you are doing.

For me, washing dishes or cooking food is quite enjoyable.  I usually put on relaxing music and start to make food for my family. While I am concentrating to cooking, I am not actively listening to the tinnitus sound. If there is a quiet moment, I'll try to listen to the background music instead of tinnitus. This way, I am not hearing (listening to) the tinnitus as long as I am making food.

After some period of time (hour or two hours) without bothered by tinnitus, I will congratulate myself... I have proven to myself that it is possible to live with tinnitus and not get bothered about it. Yes, it was only some hours, but the time can be longer tomorrow and surely it will be longer next week!

4) Relax
Tinnitus often increases when you are under a lot of stress. Logical conclusion is that the tinnitus decreases when the stress is relieved.

I am trying to relax every day while listening to a special relaxation tape, you can found similar sound files from YouTube. I am also using spike mat (acupuncture mat) every evening, or when ever I am feeling tense.

To relax, you can do what ever you want, but it should something that calms you down and relaxes you. Some people do physical exercises, like running or swimming, but for me that is not relaxing at all... :)

5) Listen to natural sounds
I have loaded several natural sounds and relaxation sounds to my iPod. I have water falls, fountains, rain, storms, singing birds, campfire, crickets and Japanese and Chinese relaxation music.

I am listening to these sounds as often as possible, actually all the time when I am at home. It gives to my ears and brains something to listen to, and specifically something else than tinnitus sound.

I have the iPod playing sounds also during the night. For the nights I have loaded "clock ticking" sound to my iPod. This way I can control the sound level for the ticking. Actually I have found that this ticking sound helps me a lot! I just place the iPod next to my bed and set the volume to comfortable level.

6) Sleep
After a bad night sleep, my tinnitus is more noticeable. At least it seems to get worsen if there are several consecutive nights with only few hours of sleep.

Thus I am trying to sleep well. Sometimes it is not possible, but if I am noticing the tinnitus more after a bad night, I can stop worrying because I know the situation will be fixed with a proper hours of sleep.

7) Medication
When the tinnitus hits you really hard, I mean really really hard, it might be a good idea to seek help from a doctor. The stress and anxiety created by the tinnitus should be minimized, because that is actually the worst part of the tinnitus, which will also lead you to the vicious tinnitus-stress circle.

If you are so stressed you can not function anymore, can not work or socialize with your family, perhaps you are crying or can not sleep at all, the doctor should see and understand your situation.






Do you agree with me or not? Do you have questions? Please, leave me a comment!

Thursday, May 10, 2012

Knitted police car

This artist has spent 3 years knitting a life sized police car replica!

 
News post:
http://yle.fi/uutiset/virkattu_poliisiauto_kurvaa_pian_kiasmaan/6089159

More detailed images:
http://www.novita.fi/blogit/576167

Friday, May 4, 2012

Hardware switch for Lenovo wireless radio truly exists

Today I spent some hours trying to figure out why I was not able use the wireless radio (WLAN) on an old Lenovo SL400 laptop.

When I tried to search for wireless networks, the machine told me to "Turn the wireless radio on". I tried to do that by disabling and enabling the wireless device, but the led for wireless connection just blinked for some seconds. Also nothing happened when I pressed Fn+F5.

I updated everything possible with Lenovo's own updater software and tried to enable and disable the wireless network card from BIOS. But still nothing, I was not able to use wlan.

While clicking around the settings, I suddenly got a popup window with the notification "The internal wireless device is set to 'radio off' in BIOS setup or hardware switch".

Because I certainly had checked from BIOS that the wireless was in use, I made the conclusion that there really HAS to be an actual physical switch for the wireless radio usage.

Really, I had to google the "lenovo wireless switch" and with a help of some forum post, I was able to locate the switch, from bottom of the front panel, out of sight. Definitely not an easy place to spot a small black switch!

Oh boy, how I felt shamed! My colleagues told me that every Lenovo has always had a hardware wireless switch. But every model may have it in slightly different place.

Well, this was my first Lenovo, so how could I knew that?!

Wednesday, May 2, 2012

LG tumble dryer error "be"

Recently I got error "be" with my LG tumble dryer.

I found out that the error message means that the drive belt is completely broken. Actually the machine also sounded like the drum was not turning at all. I could hear the motor running, but as the belt was broken, it did not turn the drum.

I had to call a repairman, who was able to change the belt in 20 minutes.

The operation cost me 160 euros. The dryer is 4 years old, and it is the first and last time when I used money to repair it. New tumble dryer costs around 400 - 600 euros, so I think the machine has reached the point where it is not economically wise to repair it anymore.

Naturally, from ecological point of view, it is very wise to continue repair broken devices.

Sunday, April 29, 2012

Fisheye lens equation - Simple fisheye effect with one function


I am interested in many kind of computer algorithms, including algorithms for computer graphics, digital image processing and 3D-graphics.

In one of my projects I needed to have "fish eye lens" like effect, and tried to find easy equation or ready function from the internet. To my surprise, there were not complete functions available, just theories and images how it can be achieved. 

Here is a brief tutorial and loop how to create fish eye -effect to any image. The function is written in Java, but as you can see, it is easily rewritten with any programming language. 

If you find this article and function useful and you will use it in your own projects, please refer where the source came. In any case, leave a comment. Questions and requests are welcome!

What is fish eye effect?

Fish eye effect is a mirror effect which happens when the image is drawn on to a surface of a sphere or a hemisphere. The surface does not need to be a perfect sphere, it can also be paraboloid or have other kind of curve as a surface.

Common effect is, that the image is "zoomed" in the center and "shrink" at the edges. The image is usually round (because we are dealing with spheres) but the image can also be clipped to be square.

Mathematics

What we need is a function which maps any pixel from the image to a surface of a sphere. 

In this fish eye effect, we are not using equations for a sphere, but an equation for unit circle:

x^2 + y^2 = 1 
Solving y
y^2 = 1 - x^2
and then finally
y = sqrt(1 - x^2) 

Because we are limiting all our values between 0.0 and 1.0, we can create values for nice arc when x goes from 0.0 to 1.0.


For example, in the image we have marked x-position 0.75, and we can calculate y-position substituting x in y = sqrt(1 - x^2), which gives us y = 0.66.

For our purpose, we will flip the curve with subtracting the result from 1.0:

d = 1 - sqrt(1 - x^2)

This curve will give us values for the difference of the distance of the source pixel and destination pixel, from the center of the image, when mapping from plane to sphere. 

The new distance is then the original distance added with the difference:

r' = r + d  (r' > r)

Polar coordinates

The normal screen coordinates (two dimensional Cartesian coordinates, simply x- and y-axis) are difficult when dealing with trigonometric functions, because the input values are typically between -1 to 1 and the angles are in radians from 0 to 2*PI.

Everything becomes more easier when you change the screen coordinates (x,y) to polar coordinates (r, theta). This is done with simple functions:

From Cartesian to polar:

    r = sqrt(y^2 + x^2)
    theta = atan2(y, x)
    
From polar to Cartesian:

    x = r cos(theta)
    y = r sin(theta)

In polar coordinates, any point in the image can be accessed with the angle (theta) and distance from center (r).

Now we are able to map any (x,y) pixel to polar coordinate (r,theta), then CHANGE the r, and map it back to (x',y'), and the pixel remains at the same line going through center of the image!

Algorithm 

What we need:
  1. the distance from center of the source image to any pixel (x,y) in the same image
  2. the position (x', y') where the pixel belongs in the fish eye image
In the following pseudo code, we are using polar coordinates. The key part in the whole process is to use polar coordinates and this fact: The actual pixel translation from 2D-image to sphere surface is done with manipulating the distance from center (r).

Pseudo code:

for each pixel (x,y)
    normalize (x,y) to (nx, ny) to be in range [-1,1]
    calculate distance from (nx, ny) to center (0,0)
    convert (nx,ny) to polar coordinates
    calculate new distance from center on the sphere surface
        The new distance is r' = r + (1 - sqrt(1 -r^2)) / 2
    translate (nx, ny) back to screen coordinates (x',y')


The image above shows how Points P1 and P2 will be displaced to P1' and P2', so that the angle remains the same. In other words, the point is displaced along the original line towards the edge of the unit circle. The distance from the center tells us how big is the displacement. In the center and near the center the displacement value is zero or almost zero. Near the edges displacement value grows towards value of 1.0.


The image above gives the idea behind the displacement value. For every pixel in the result image plane, there is a pixel from source image plane. In here, the source image plane is stretched and curved. It may be easier to understand, if you think a one single line instead of the plane. Along that line, the pixels are almost normal at the center, but towards the ends, the pixels are fetched further and further away from the center.

Most important thing


The most important thing is to understand, that for each result pixel, there is a source pixel, on the same line going through the center, but with a greater distance.

The source 

public static int[] fisheye(int[] srcpixels, double w, double h) {

    /*
     *    Fish eye effect
     *    tejopa, 2012-04-29
     *    http://popscan.blogspot.com
     *    http://www.eemeli.de
     */

    // create the result data
    int[] dstpixels = new int[(int)(w*h)];            
    // for each row
    for (int y=0;y<h;y++) {                                
        // normalize y coordinate to -1 ... 1
        double ny = ((2*y)/h)-1;                        
        // pre calculate ny*ny
        double ny2 = ny*ny;                                
        // for each column
        for (int x=0;x<w;x++) {                            
            // normalize x coordinate to -1 ... 1
            double nx = ((2*x)/w)-1;                    
            // pre calculate nx*nx
            double nx2 = nx*nx;
            // calculate distance from center (0,0)
            // this will include circle or ellipse shape portion
            // of the image, depending on image dimensions
            // you can experiment with images with different dimensions
            double r = Math.sqrt(nx2+ny2);                
            // discard pixels outside from circle!
            if (0.0<=r&&r<=1.0) {                            
                double nr = Math.sqrt(1.0-r*r);            
                // new distance is between 0 ... 1
                nr = (r + (1.0-nr)) / 2.0;
                // discard radius greater than 1.0
                if (nr<=1.0) {
                    // calculate the angle for polar coordinates
                    double theta = Math.atan2(ny,nx);         
                    // calculate new x position with new distance in same angle
                    double nxn = nr*Math.cos(theta);        
                    // calculate new y position with new distance in same angle
                    double nyn = nr*Math.sin(theta);        
                    // map from -1 ... 1 to image coordinates
                    int x2 = (int)(((nxn+1)*w)/2.0);        
                    // map from -1 ... 1 to image coordinates
                    int y2 = (int)(((nyn+1)*h)/2.0);        
                    // find (x2,y2) position from source pixels
                    int srcpos = (int)(y2*w+x2);            
                    // make sure that position stays within arrays
                    if (srcpos>=0 & srcpos < w*h) {
                        // get new pixel (x2,y2) and put it to target array at (x,y)
                        dstpixels[(int)(y*w+x)] = srcpixels[srcpos];    
                    }
                }
            }
        }
    }
    //return result pixels
    return dstpixels;

Example pictures 

Original

After applying fish eye function