Friday, 26 December 2014

The World Reacts to the Mighty Jingles - #1 North Korea

We've all wondered, haven't we, what happens when Jingles releases a new Video?... In this new series I aim to help solve that mystery.... This week, North Korea



Check back each Friday at 18:30 UK time for the next thrilling instalment, where might we find Jingles being Enjoyed?

Tuesday, 23 December 2014

Programming - Elite Dangerous Tools - Image Stitching

I've been working on the Tools for Elite, however I'm having problems with the current release of the game itself, it keeps just locking my machine.  And I don't mean it locks the process, I mean the whole machine locked solid, I have to power cycle to get out of the problem.

This is a solid, stable, machine, only Elite Dangerous does this and the windows log contains information that a part of Elite Dangerous went to 100% CPU and would not come back down again.

I had reported this in both Beta and Gamma builds, but the ticket got closed, and so now in release I'm simply not playing.

But, on with the image stitching, without any of the Elite Dangerous market data I need to look at how to capture the images, and the market listing is long, it turns into several screen shots, so with the area of the screen I'm going to capture know I just need to scroll down, let the image capture, and then stitch the images together...

Let us mock up some Market data...




My first pass stitches the 2nd and 3rd images together...


Then I stitch this partial to the 1st image.


If you look closely you can see there's a repeat pixel, so I need to crop one pixel off of the pieces before I paste them together, but other than that it worked....

I'm currently thinking about looking into OpenCV, but I need a few days reading time first.

British Gas - Billing & Indian Bullshit

You may recall I mentioned problems with cold calls from British Gas in August?

Well, they're up to the same tricks, local Nottingham number, so I answer, loads of clicks and then a very noisy call centre in the background and an Indian woman shouting at me, insulting me, calling me a fool.

I'm not going to go through security with you, you called me, what you're effectively asking me to do is tell a stranger who just called me out of the blue on an unknown number my private personal information....


When I challenger her on this, and asked for a call back number, she even avoided the question and told me "we have very many numbers"... Yeah, well give me one!


Needless to say I went back to them myself and sorted my account, but I also reported to complain about this woman, she was so annoying, obtuse, rude and insulting... I posted my report at about 5pm yesterday (22nd December 2014)...

You want to see their reply...?


So, there's my mail into them, and I just got a reply... 12:21... Right... Here's the reply content...


Yes, the reply is blank, it's just a copy of my mail to them... Classic British Gas... Classic, fantastic Customer Service, fantastic... And British... Should be fucking "Indian Gas", so tired of this crap with them.

Wednesday, 17 December 2014

How to Get into PC Gaming (PC Build Advice)

You want to get into PC Gaming?... But you don't know where to start and think it'll cost you the earth?

Ner, lets get straight in here and say, you can spend as much or as little as you like, but you do not ever need to break the bank and certain parts of your built machine will be with you a long time.

What am I talking about?  Well, unlike your console which you buy off the shelf as a complete unit a PC is really a whole collection of different pieces, which over time you can upgrade and keep current.

In general I consider there to be four main sections to your PC:

1. Processor (CPU), Memory (RAM) and motherboard (main circuit board)
2. Graphics Processor(s) (GPU)
3. Case, Power & Cooling Accessories
4. Screen, speakers, controls (Mouse and Keyboard)

Different sections of these pieces are upgradable at different rates and for different price brackets.  Yes ultimately as a PC Gamer you have to buy a whole system.

But in the longer term you can save money by buying a system with some of these parts to last.

A good example is that you could buy a Dell PC straight from them, and pay slowly with their finance deals, however, I can tell you now you'll never be able to use that case again!  You can never rip the 5 year old guts out of a Dell and put the latest CPU/Motherboard/RAM package into that case.

So, this is where I'd start, buy a good case, which is large enough to handle any motherboard.  The key specification here is "ATX" this is the standard side.  Many Dell and other manufacturers cases are "BTX", and you can also get shrunk down "mini-ATX" and even "micro-ATX" cases.  But the standard size case is "ATX".

When considering the case you must also make sure there is room for drives to be added inside.  And space for cooling and power equipment.

My case (as seen here) was purchased in 2007, and has now had three different machines built within it's walls.   It's the same, unmodified, working case I bought for about £90.  Which means it's cost me about £13 a year to own that case, and it's still going strong, still has my main gaming PC within!

My power supply, the power supply sits inside the case, and again so long as it's a standard power supply it will power any machine, what you might want to ensure however is that you have a fairly decent amount of "watts", this is the unit of measure for the total output of your Power Supply Unit (PSU), and you're going to need about 250 watts for a basic desktop processing/internet machine, 350 watts for a simple media center, 450 watts for a basic gaming machine and 650 watts or more for a powerful gaming machine.

As you add more equipment into the machine, the more power draw it has, so the more regulated (safe) power the PSU has to handle and dish out to each component inside.

Fans, or cooling, if you're new to PC's then just understand when you come to PC Gaming the components inside the machine pump out a lot of heat, this has to be extracted from the machine, and fresh - colder - air has to be drawn in from your room.  To do this we mount fans in our case, either drawing in from the front and pushing out the back, or in from the bottom and pushing out the top.

Some components like your processor and your graphics card can arrive with fans equipped, but you still have to change the air inside the machine regularly with fans.  To keep them quiet you can go (as I explained in my article) with specialist build fans, or for simplicity just get the largest slowest revolving fans you can, the larger and slower a fan - drawing enough air - the quieter.  It's no good having too slow a fan however, you still need to get air through, just doing it gently makes for less noise (90% of people I meet complaining their PC is stuggling, slow or too noisy, either have tiny fans spinning at crazy high speed making lots of noise, or simply don't have any ventillation; other horror stories about how dirty a PC case can get can be found on the internet).

So, your case, the power supply and your fans can pretty much move from build to build to build as you progress, investing in them now makes for much cheaper new systems as you move up the scale.

Next your PC needs some storage, you need for gaming fast storage, so I'd recommend you get an SSD (or solid state drive) for your games to run from, and then a fast (7,200 RPM) hard drive for the main storage of data.  You can find much better guides to this than here, so for now get what you can afford, one decent 7,200 RPS SATA hard drive is sufficient!

This drive can then be used in any machine you put together later.

That's the end of the sort of "unchanging" part of your machine, obviously a keyboard, mouse, screen and speakers can also be lumped into that "unchanging" category, spend as much or as little as you can afford... There's obstensibly no difference between a £5 keyboard from Asda and a £90 mechanical from Cherry when you're starting out... One day you'll use a better keyboard than your own and want the other, but by them you'll know whether PC is the thing for you.

So, now onto the most malliable, and upgradable, part of your system... The Motherboard, CPU and memory.

You need to pick what you want from your gaming experience, and I'm going to talk about Intel processors, the current three classes of Intel processors are "i3", the "i5" and the "i7".  You can get these in many flavours, but you can change them later, if you have a budget, look for a CPU which fits your budget and note down the connector type (or socket type) for it, then look for the top processor with that same connector type.

This will give you a good idea of the upgrade path your machine will take as it ages, because yes, you can change the processor up from a cheaper one to a more expensive one, or even find the current most expensive one on discount/auction sites later on and upgrade your machine.

Lets say today we've found a Core i5 processor which has a clock speed of 3.0ghz, and we know it has a contemporary Core i7 with the same socket and a clock speed of 4.02ghz, this will be our upgrade path.

What we need now is to find a motherboard with that connector and which supports both chips.  This essentially is a fiddly google search, but do check with the supplier of your parts if you're unsure, and also ask for their confirmation that the motherboard you buy from them supports both chips - this way if it actually doesn't you can sort things out with them!

So, now armed with information about the Motherboard and processor together we need think just about two more things.

The first is the Memory for the machine, you need to buy memory which is compatible with the motherboard you purchase.  Luckily the manufacturers of mainboard come to our rescue, once you've got an idea of the board you want you can just go to their support website and download the manual, before you spend a penny.

Reading this will give you a list of the compatible, or even recommended, memory, you can then simply purchase this for use.

This is the "safest" thing to do, because lots of people will simply dive for the cheapest memory thinking it makes no difference, this will result in their having a poor time with stability; meaning their machine will crash a lot.

Memory gets hot, so you may want to consider a memory heat-sink (this is a metal fin which attaches to the memory to spread heat away from the electronic chips) though some memory already come with fins attached.  You can also get fans for your memory to cool it even more, the cooler the better.

Your CPU has to have a CPU too, both AMD and Intel CPUs (purchased in a proper box) come with a cooler sufficient for their standard use, when you're starting out this cooler will be more than enough.  However a high performance cooler could be yours for around £30 and last you a long time, the only complexity is again any cooler you buy has to fit the processor socket on your motherboard.

So, in review, you can buy a PC built off of the shelf, ready to go, however, you won't know what parts are inside it, nor if any of the parts can be upgraded as the system ages.

There are services you can use whom will build systems exactly to your specification, PC Specialist is one such offering.

Or of course, for a small fee, or gifts, I can help!

Any questions, post them below or e-mail me!

Monday, 15 December 2014

Seriously? Vasility?

I've just had a conversation with a senior developer at a major company related to the work I perform day to day...

And after he'd done explaining something he asked "Any questions"...

I tentatively said "Yes, could you clarify what you mean by 'Vasillity'"...

That's what he was saying "Vasility"... he doesn't - as far as I can tell - have a speech impediment, he doesn't have a cold and he's not usually an arsehole, so I was very surprised when he said to me...

"Don't be a smart ass"...

I'm not being a smart ass, I really didn't know what he meant by "Vasility"...  he got very uppity with me and he left the conversation there.

About a minute later one of the other chaps whom I work with explained "he meant facility, he just can't say it"...

I didn't know this... It's a pretty strange situation, and he can say a whole bunch of other "F" works, including FUCK, which I've heard him say many times; if he'd been saying "vuck" all these years I'd have had a clue.

Anyway, Vuck it, I'm off to use the Vasilities.

GetACoder - Don't Use Them!

I've been using the website "GetACoder", to provide coding and try to earn some extra cash to pay for the move a head of us, it has been a hit & miss affair.

I've provided, what I thought was good work, to one company and had good feedback and payment from them.  But they've done mysteriously silent on the whole development; considering there were grand designs beyond the basics I'd already given this was a little sad, as I perhaps thought I might have a second quiet little income.

But then I've had lots of silence from the other tenders I've put in, one chap wanted work from me, but then didn't want to pay (despite my having an hourly rate and bidding on his job specifically), hey ho...

I also noted a great trend in visitors to the site are students, from around the world but primarily from the US, whom seem to post their Computing/Programming course work on the site for review.

Now I've liberally read these requests for work, seen what they are, realised they're cheating and reported them to their tutors where I've been able to identify them.  One lot I not only identified it was course work, but I had the course code, the tutor name and the individuals involved.  Of the half dozen professors I contacted about this only one replied, kudos to him, but to the rest of the US Graduate Computer Programming market, be very ware, you maybe hiring people who have done their course work via Calcutta!

Where else did this take me?  Well, frustrated with the site itself I then tried to withdraw the funds I'd earned, I had $100... For putting me in touch with the contract the site had already taken $15, leaving me with $85.

To withdraw it I also have to pay 1.9% PayPal plus $0.15 again to the site, so this is a loosing battle to get your money.

But it's doubly not worth it when you finally get through the withdraw process, only to see it error and tell you withdrawls need to be over $100, and for some payment processes you need to have over 3 completed tasks for people!

It struck me as rather odd, so I took a look, and the site doesn't really have a location, they state on it that it's got UK, US, Hong Kong etc offices, but there are no such offices.  There is an address in portugal linked to the company who owns the copyright of the site, and so I thought I'd give them a shout and see if they could help.

I did get some help, a customer service rep opened a support ticket for me, but they basically said to withdraw my money they would have to lock my account for 2 years... Go a head, lock it, you're going to loose my custom?!?!?!

This simply made no sense, it was utter none-sensical, and then they started to almost threaten me with their sites being under the rule of the laws of Nevis... I'd never heard of Nevis, so I looked it up, and it is not Nevis, their TOS is actually wrong, they're talking about the Isles of St Kitts and Nevis, known commonly here in the UK as St Kitts (no offence to the population of Nevis, it's just St Kitts we know, Nevis not so much, and "Nevis" is the name of the highest mountain here in the UK that's all).

So, I figured I'd askt he government of St Kitts and Nevis themselves how to track this company down, to see if they actually are operated and have holdings on the isle of Nevis, lets face it in the EU; where I performed the work; you can't be based over seas and you can't withhold peoples money, Amazon knows that all too well...

They site, but not the government, got back to me, so I'll chase that up and see if someone wants to talk to me, if it takes a 15 minute internet phone call, I'll make it.

Because this whole system "GetACoder" has is just a bit off, it seems very much as though they want to keep hold of my money, to earn interest on it one would presume "it takes 20 days to perform a withdrawl for you, and we lock your account for 2 years"... Lock it, go a head, you'll just loose my custom!

And why 20 days?... A PayPal transaction takes minutes, they could see from the ticket that a) I have an account b) I had to log onto their site to sent the message c) I exist, they can just look me up online, you see as opposed to the myriad of far east, Indian-subcontinent and other none-descript users of the site I'm in Britain, we have certain standards and are happy to question odd systems.

The system at GetACoder is very odd, the jobs posted are very odd, all in all, I'd have to say now to give it a miss.

I may even come back to this post and let you know if I get my money.

Saturday, 13 December 2014

YouTube Search Results

Just watching Jingles latest offering, and I was very surprised by one of the Thumbnails in the "What to watch next" shown by YouTube at the end of the video...

Quite what the lady is up to, we can only leave to our imagination, but why is she there?... Well it's a classic miss-leading thumbnail (very annoying) and is a documentary about torture.

This isn't the first time a search I've invoked because of Jingles has lead to strange search results... Anyone remember the result of the search I did regarding searching for WarThunder Ground Forces before they were released?


Friday, 12 December 2014

Programming - Elite Dangerous Tools - Sobel Edge Detection (with Full Code)

Update: You can now support this project at Patreon!

Forearmed with our greyscale code we can therefore look at the Sobel mask to give us a nice crisp delimitation between the background and the text on our screen shots... Lets say we capture the top half of the market prices screen upon landing... We can capture the screen shot, convert to grey scale and then sun the sobel mask over the pixels to give a crisper showing of the text for our later OCR work...

There are many explanations of how Sobel Operations work, however they are very mathematical... Simply put we have each pixel (except the ones in the edge) value and for it and each neighbour we apply a mask... Lets draw some simple pictures....

Below we see the grid of pixels in our image...
Each pixel is made up of a value for Red, Green and Blue, but because the image is greyscale all three of these values are the same number, so we can just take one of them...
Next in code we need two masks, these are 3 x 3 grids of numbers, these values in the grid are applied to each pixel, except the edge pixels in our image.












So, from 1 until 1 less than the width, from 1 until 1 less than the height... Sliding the middle of the mask over the pixel target we then apply the mask to each pixel value around and including the pixel.

So we calculate and sum these values writing them into the resulting same pixel location on the end result image...
Saving the image result we see the edges of the shapes within highlighted...


Find the full code here and the previous step code for greyscale here.

Thursday, 11 December 2014

Programming - Elite Dangerous Tools - Greyscale (with Full Code)

Update: You can now support this project at Patreon!

One of the problems in our tools to capture market data and read the data optically is to take screenshots from the screen, or be provided screenshots by the client itself, load them and convert them to greyscale.

Now, my preferred method of converting to greyscale is going to use CImg to load the image into memory.

I always load as "unsigned characters" (raw bytes) of data, and I'm going to assume we've got the file on disk as a bitmap - just to save us the complexity of Jpeg or PNG loading for now - so on disk we have an image which is a colour Bitmap.

To load this into CImg we want to create a "cimg_library::CImg<unsigned char>" instance, so the first thing I'm going to do is typedef this as our "Bitmap" type:

typedef cimg_library::CImg<unsigned char> Bitmap;

With this type we then need a helper function, which gives us a loaded image:

Bitmap* LoadImage(const std::string& p_Filename)
{
return new Bitmap(p_Filename.c_str());
}

Of course there are already classes called "Bitmap" in the C++ space, so for safety I'll wrap everything in the final code in a namespace of "Xelous", watch out for that later!

Now, with our image in hand we need to understand how CImg lets us parse over the individual pixels, well the CImg class provides us with a function called "data" which takes the x, y and z of the pixel (z being the layer, but I always use 0) and then the channel as an integer.

Our channels are:

enum ColourChannels
{
Red,
Green,
Blue
};

So red is zero, green is one and blue is two.  Taking a look at code to just output the RGB of each pixel therefore looks something like this:

#include <iostream>
#include <string>
#include "CImg.h"

typedef cimg_library::CImg<unsigned char> Bitmap;

Bitmap* LoadImage(const std::string& p_Filename)
{
  return new Bitmap(p_Filename.c_str());
}

enum ColourChannels
{
  Red,
  Green,
  Blue
};

int main()
{
  Bitmap* image = LoadImage ("C:\\Images\\Image1.bmp");
  if (image != nullptr)
  {
    for (int y = 0; y < image->height(); ++y)
    {
      for (int x = 0; x < image->width(); ++x)
      {
        unsigned char l_r = *image->data(x, y, 0, ColourChannels::Red);
        unsigned char l_g = *image->data(x, y, 0, ColourChannels::Green);
        unsigned char l_b = *image->data(x, y, 0, ColourChannels::Blue);
      
        int l_redValue = static_cast<int>(l_r);
        int l_greenValue = static_cast<int>(l_g);
        int l_blueValue = static_cast<int>(l_b);
      
        std::cout << "Pos (" << x << ", " << y << ") =";
        std::cout << "[" << l_redValue << ", " << l_greenValue << ", " << l_blueValue << "]" << std::endl;
      }
    }
    delete image;
  }
}

The output from this program looks something like this (assuming you have "C:\Images\Image1.bmp" present)...


As you can see each pixel position is slowly listing out it's colours, this is a really slow boring program, but it opens up to us the inside of the bitmap, we could for example swap every pixel of one colour for another... and save the image again...

What does our original image look like?...


Lets just set every pixel to black, or zero...

int main()
{
  Bitmap* image = LoadImage("C:\\Images\\Image1.bmp");
  if (image != nullptr)
  {
    for (int y = 0; y < image->height(); ++y)
    {
      for (int x = 0; x < image->width(); ++x)
      {
        unsigned char l_r = *image->data(x, y, 0, ColourChannels::Red);
        unsigned char l_g = *image->data(x, y, 0, ColourChannels::Green);
        unsigned char l_b = *image->data(x, y, 0, ColourChannels::Blue);

        int l_redValue = static_cast<int>(l_r);
        int l_greenValue = static_cast<int>(l_g);
        int l_blueValue = static_cast<int>(l_b);

        int l_n = 0; // Pick a colour

        *image->data(x, y, 0, ColourChannels::Red) = static_cast<unsigned char>(l_n);
        *image->data(x, y, 0, ColourChannels::Green) = static_cast<unsigned char>(l_n);
        *image->data(x, y, 0, ColourChannels::Blue) = static_cast<unsigned char>(l_n);
      }
    }
    image->save("C:\\Images\\Image2.bmp");

    delete image;
  }
}

The new parts here are of course the RGB being set back into the pixel and the image then being saved.

The output is a very boring looking image...


So now what kind of things can we do to the value of "int l_n" here to give us grey scale?

Well, there are a few different algorithms and other bloggers do a better job than I will at explaining them...


The simplest is to add the red, green and blue values together then divide them by three to give us the average colour channel value, assigning this back to all three colour channels we create a shade of grey...


This code however looks like this:

int main()
{
  Bitmap* image = LoadImage("C:\\Images\\Image1.bmp");
  if (image != nullptr)
  {
    for (int y = 0; y < image->height(); ++y)
    {
      for (int x = 0; x < image->width(); ++x)
      {
        unsigned char l_r = *image->data(x, y, 0, ColourChannels::Red);
        unsigned char l_g = *image->data(x, y, 0, ColourChannels::Green);
        unsigned char l_b = *image->data(x, y, 0, ColourChannels::Blue);

        int l_redValue = static_cast<int>(l_r);
        int l_greenValue = static_cast<int>(l_g);
        int l_blueValue = static_cast<int>(l_b);

        // Average
        int l_Sum = l_redValue + l_greenValue + l_blueValue;
        
        double l_Average = l_Sum / 3.0;

        int l_n = static_cast<int>(std::round(l_Average));

        *image->data(x, y, 0, ColourChannels::Red) = static_cast<unsigned char>(l_n);
        *image->data(x, y, 0, ColourChannels::Green) = static_cast<unsigned char>(l_n);
        *image->data(x, y, 0, ColourChannels::Blue) = static_cast<unsigned char>(l_n);
      }
    }
    image->save("C:\\Images\\Image2.bmp");

    delete image;
  }
}

This is the average algorithm... And we could have placed this code into a function to use, taking in the three unsigned chars and giving us whatever value... Implementing functions for the other greyscale algorithms as we go along... My implementation goes like this, adding the algorithms as a selection:

///<Summary>
/// The types of Greyscaling algorithms
///</Summary>
enum GreyscaleAlgorithms
{
  Average,
  Lightness,
  Luminosity
};
Our function can then look like this:

void ConvertToGreyscale(Bitmap* p_InputImage,
  const GreyscaleAlgorithms& p_Algorithm);
  
And our changes inside relate to our calculating the new pixel value before we assign it back to all three channels:

double l_a = 0;
switch (p_Algorithm)
{
  case GreyscaleAlgorithms::Average:
    l_a = DoubleToInteger(Average(l_r, l_g, l_b));
    break;

  case GreyscaleAlgorithms::Lightness:
    l_a = Lightness(l_r, l_g, l_b);
    break;

  case GreyscaleAlgorithms::Luminosity:
    l_a = Luminosity(l_r, l_g, l_b);
    break;
}

int l_n = DoubleToInteger(l_a);

///<Summary>
/// Average Grey
///</Summary>
double GreyscaleHelper::Average(const unsigned char& p_red,
  const unsigned char& p_green,
  const unsigned char& p_blue)
{
  int l_t = static_cast<int>(p_red)+
            static_cast<int>(p_green)+
            static_cast<int>(p_blue);
  return l_t / 3.0f;
}

///<Summary>
/// Lightness grey
///</Summary>
double GreyscaleHelper::Lightness(const unsigned char& p_red,
  const unsigned char& p_green,
  const unsigned char& p_blue)
{
  int l_max = std::max(
      static_cast<int>(p_red),
        std::max(
          static_cast<int>(p_green),
          static_cast<int>(p_blue)));
  int l_min = std::min(
      static_cast<int>(p_red),
        std::min(
          static_cast<int>(p_green),
          static_cast<int>(p_blue)));
  return (l_max + l_min) / 2.0f;
}

///<Summary>
/// Luminosity grey
///</Summary>
double GreyscaleHelper::Luminosity(const unsigned char& p_red,
  const unsigned char& p_green,
  const unsigned char& p_blue)
{
  double l_red = 0.21 * static_cast<int>(p_red);
  double l_green = 0.72 * static_cast<int>(p_green);
  double l_blue = 0.07 * static_cast<int>(p_blue);
  return (l_red + l_green + l_blue);
}

///<Summary>
/// Double rounded to integer
///</Summary>
int GreyscaleHelper::DoubleToInteger(const double& p_Value)
{
  return static_cast<int>(std::round(p_Value));
}

This probably looks like a lot of gibberish, but no it really is Greyscale code... On this page... Is the complete source code for this portion of my work so far, but here are some examples from my original image...

Note: I can't remember where I got the original image - the internets obviously - so if this lovely bowl of fruit is yours, let me know... I'll give credit.

Average

Lightness

Luminosity

Wednesday, 10 December 2014

Programming - Elite Dangerous Tools in C++

Update: You can now support this project at Patreon!

I'm back at work, and very busy, we're still waiting on the house sale... But I've got my man lab, roughly, back together... In fact I've got a little improvement in things as I'm back to a single room with shelves all around me so I can turn from my work, pick a DVD and play it whilst working!

This has meant I've re-watched the entire Black Adder series, I'm in the middle of re-watching the Lord of the Rings (yes the special extended edition)...

But, what am I working on?... Well, I'm still playing WarThunder, but I'm also playing Elite Dangerous, and I've some history with Elite, specifically Frontier.  Where I ran "The Frontier Club" later the "Frontier Users Group"... More about which later...

But as part of the club I created a series of tools, in Pascal, on which you could record your kills and document the systems visited, this was really clunky basically you noted things down on paper then when you'd finished playing the game you rebooted your Atari ST to run the tools and insert your new found knowledge, building something which I later would call a data-sheet... A database come spreadsheet hybrid... But which you could print out from the computer, making everything look dead neat and tidy.

I used to have reels of system information and lists of kills counted on the wall, and each weekend after playing Frontier, I'd laboriously enter new information, run a tally and print out my new score sheet and pin it on the wall... I don't know if any of the club members did this, but I remember getting some feedback from users asking for the source code... Though what seemed to amaze most club members was my using "Timeworks" desktop publisher on my ST and from my Citizen 120D+ 9 pin printer producing real looking news paper style news letters... I think I actually got more requests as to how I did that, and proof with photographs requested, than I did requests for save games!

Anyway, I remember that, let me know if any readers were club members!  And I remember the frustration of noting stuff down and then manually updating the system... This was a limitation of the Atari ST, which apart from limited TSR programs you could only run one application at a time, there was no process switching at all.

Of course on a current PC with Elite Dangerous running we can process switch, we run tens, dozens, even perhaps hundreds of processes at the same time as you're playing the game on your machine.

And we could just hook into the memory of Elite Dangerous from another process and scrap out any information we wanted, however, Frontier Development have kindly asked that tools not do this, and that they not wiretap the network connection and capture information from it... Because doing either of these techniques one could, and some tools did, scrap out the market data to optimise peoples play experience; just like us old veterans did with the original titles "back in the day".

So, if we can't scrap the memory or intercept the transmissions, and of course paper and pen are too labourious, what can we do?  Well, I started out with Open Office, a spreadsheet open and created a tab for each system I visited I noted down for each station the basic goods available and I have dozens of tabs, hundreds of trade goods, multiple resource extraction sites listed and even combat sites listed... And it's totally inaccessible, it's very hard to update, slowly goes out of date as the markets change in game, and it take almost as much time to generate this information by hand as spend playing the actual game.

It does give me a great advantage, and starting a new game I soon jumped from 1000 credits to three new ships and a healthy 500,000 credit bank balance... Is this useful... Most certainly... Is it worth the effort?... No.

I'm a busy married man, I work all day, I try to enjoy the limited game time I get and updating a massive amount of spreadsheets seems a bit more like hard work than entertainment... If you think that spreadsheets might be entertaining, you have my sincere condolences.

Locked out of accessing the client or it's network traffic is there some way in which we could scrap data out of the game then?  Well, we humans do it all the time, we simply read the screen... So I set about writing a first tool, this was a very simple took which hooked into the windows keyboard controller at the lowest level and if I pressed a key (even in a fullscreen client) the tool took a screenshot and stored it...

I could therefore capture the market data as I landed at each station.  But I again had to manually enter the station and system name... Adding these images to a series of tabs I had a quick way to switch between images of market data... But it had some problems... One problem (and a persisting problem) is that on my screen at 1680x1440 I could only see part of the market listing at a time, I had to scroll down and take two images to see the whole market, meaning I needed to write another toll to stitch the two images together to get a complete listing... This image stitching became the focus of another of my forays into Image Processing.

Next I wanted to uniformly present the text, so I used previous code I'd created (in C#) ported it to C++ and so was able to drop out the colours... In grey scale the markets looked nicer.

This then lead to a mini-eureka moment... With this complete market list, in black and white, could we apply the Sobel operation I've previously looked at and so give ma a crisp edge to the text?

Yes, I could... And did... So now, could I find an OCR tool to read this text for me?

And this is where I wanted to start to talk about the development, the image processing to this point has been plenty of code to get to grips with, both the windows code to gather the raw image, then stitch and prepare the greyscale copy and apply the sobel mask is a big piece of code and making it pretty code was also a challenge as you're always trying to get things done rather than make code others, or even yourself, can come back to later.

But OCR... Making code to read the text... That's a huge new challenge for me, something I've touched on before, but never put my teeth into.

You can buy off the shelf OCR solutions, but I don't, and I'm pretty sure not many of my readers have the $6000 odd dollars they're asking for.  We could use the Microsoft Office OCR plug-ins... But, this locks us to Microsoft, locks us to using Office and paying a license fee... I don't own office and don't want to make a tool, which others might use, that is subject to such a fee.

What options for OCR are there for me?.. Well I could look up and implement some Neural Network stuff... but I've never really understood Neural Networks, those that know about them tend to spout al-sorts of mathematics and never present code, where code is presented it either doesn't work or is uncompilable.

What have the open source community got?... Well there is a series of tools around, one called Tesseract caught my eye, but it was wholly unwieldy, it didn't want to compile on windows and it relied on several dozen other libraries each of which had to be pre-built or would not build on windows.

Hows about simpler OCR?... Pattern matching?... Yes, these are options as well...

This series of developments will form the focus of my next few programming posts, so stick around.