Sidebar Menu

Projects

  • Dashboard
  • Research Project
  • Milestones
  • Repository
  • Tasks
  • Time Tracking
  • Designs
  • Forum
  • Users
  • Activities

Login

  • Login
  • Webmail
  • Admin
  • Downloads
  • Research

Twitter

Posts by stumathews
Stuart Mathews
  • Home
  • Blog
  • Code
  • Running
  • Gaming
  • Research
  • About
    • Portfolio
    • Info

Implementing a Vignette

Details
Category: Code
By Stuart Mathews
Stuart Mathews
26.Jan
26 January 2021
Last Updated: 05 February 2021
Hits: 6288
  • Python
  • Computer Vision
  • Computer Graphics

I recently had a task to create a vignette of a picture. This is a technique in Computer Vision or digital signal processing whereby as you move closer and closer towards the centre of the image, the pixel intensity increases:  

When first approaching this problem, I could not understand how, from a dense matrix of colour information, you could determine how far the pixel that you were processing was from the centre of the image. I confirmed, that no position information is available within the pixel itself (it just contains raw colour information). Finally, it dawned on me that you could use the coordinates of the image matrix to create a vector to represent the centre point, ie. the offset x and y from an origin.

But where is the origin?

I first thought I'd have to use the centre of the image as the origin, meaning all my pixels co-ordinates would need to be relative to that, which would have been a pain as I'd have to work out how, say each pixel in the matrix[x][y] would probably need to be represented differently when relative to not matrix[0][0] but the centre of the image!

Then I realised that it could keep the origin as [0][0] in the matrix ie image[0,0] for both the centre point and each respective pixel and then it could thus be represented by a vector displacement from that same origin. This was a breakthrough for me. Not only that, you could then generate a new vector for each pixel this way - all using [0,0] in the image matrix to represent a distance of that pixel from the same origin. 

So, now you have two 2D vectors from the same origin, one that points at the centre of the image ie [max_cols/2, max_rows/2] and you have a vector that is [x,y] for each pixel you are currently processing. You can now subtract the vector representing the centre point from the pixel vector you are currently at, ie this would result in the vector between the two, which if you can calculate the magnitude thereof, will be the distance between the pixel you are on and the centre of the screen - ie its the hypotenuse between the two sides (of the two vectors). 

The length of the resulting vector can be easily by passing in the vector to np.linalg.norm() - ie get the norm of the vector ie the (length or magnitude) and this the distance. I guess you could also do this yourself by squaring the components of the vectors, adding them up together and taking the square root. But this is much easier.

Now you can use that distance to drive the intensity value at that pixel!

With the distance(d), you can derive the relative intensity using a function of d and max length of the image to give the intensity i.e brightness(d,img_max) to assign for that distance from the centre. That function produces e raised to the power of the ratio of distance to width. This equation was given and I've represented as the brightness function in the python code below:

\[ f(x,y) = e^{(\frac{-x}{y})}
= \begin{cases}
& \text{x is distance from center} \\
& \text{y is the width of image }
\end{cases} \]

As the image was already in 24-bit RGB colour, I converted it to HSV so that I could manipulate the V component, which corresponds to the intensity. This is not immediately and easily determinable from the RGB data.

I could then manipulate the V component by doing a simple 1d vector x 1d vector multiplication to create a mask that multiplies only the V component with the brightness, leaving the Hue and Saturation intact (I multiplied those by 1(identity)) 

This can be more concisely be represented in this Python script I wrote: 

# Change intensity of pixel colour, depending on the distance the pixel is from the centre of the image

from skimage import data
import numpy as np
import matplotlib.pyplot as plot
from skimage import color, img_as_float, img_as_ubyte
import math

# We can use the built in image of Chelsea the cat
cat = data.chelsea()

# Convert to HSV to be able to manipulate the image intensity(v)
cat_vig = color.rgb2hsv(cat.copy())

print(f'Data type of cat is: {cat_vig.dtype}')
print(f'Shape of cat is: {cat_vig.shape}')

# Get the dimension of the matrix (n-dimensional array of colour information)
[r, c, depth] = cat_vig.shape
v_center = [c / 2, r / 2, 0]

# Derive the pixel intensity from the distance from center
def brightness(radius, image_width):
    return math.exp(-radius / image_width)


# Go through each pixel and calculate its distance from center
# feed this into the brightness function
# modify the intensity component (v) of [h,s,v] for that pixel
def version1(rows, cols, rgb_img, v_center):
    for y in range(rows):
        for x in range(cols):
            me = np.array([x, y, 0])
            dist = np.linalg.norm(v_center - me)
            # alternative:
            cat_vig[y][x] *= [1, 1, brightness(dist, cols)]
            # cat_vign[y][x][2] *= brightness(dist, cols)

# do it
version1(r,c, cat_vig, v_center)

# Convert back to RGB so we can show in imshow()
cat_vig = color.hsv2rgb(cat_vig)
fig, ax = plot.subplots(1, 2)
ax[0].imshow(cat)  # Original version
ax[1].imshow(cat_vig)  # vignette version
plot.show()

This was pretty interesting, and I do love it when theoretical math ie linear algebra applies to practical outcomes!

Q.E.D:

aggressive lick pic.twitter.com/40fZHFY2w1

— Animal Life (@animalIife) January 25, 2021

Functional programming paradigms and techniques

Details
Category: Code
By Stuart Mathews
Stuart Mathews
19.Jul
19 July 2020
Last Updated: 29 July 2020
Hits: 3930
  • Impressions
  • Programming
  • Game development
  • Functional programming
  • MonoGame

Since Ruby RSpec let and let! diffirences, I've been working to understand the implications of converting an existing codebase, one which is inherently imperative to one that implements and utilizes more functional paradigms. The existing codebase is a prototypical game I wrote for my final project/coursework in my Computer Games Architectures class. 

The game is written in C# and uses MonoGame as the primary game engine. 

The task at hand, is to implement distinctive elements of functional programming without changing the meaning of the game, its gameplay and rules, in effect refactoring it. 

From an implementation point of view, its important then to define what are those elements, techniques, paradigms or indeed styles that are inherent to functional programming and to which I would need to implement to be faithful to those ideals.

Functional Programming paradigms

My views are that paradigms are foundational elements, cross-cutting concerns and in this way the primary paradigms are reliability, using higher-ordered functions and ensuring immutability during computation.

One might argue that reliability and higher-order functions are unique, while immutability results in reliability (as does inherently pure functions).

Reliability and Pure functions

This is an absolute guarantee that a function will always yield the same results when the same arguments are used on subsequent invocations. Aspects of programming that undermine this guarantee as constructs or practises that may yield exceptions to this idea.

This includes the introduction of varying probability such as this potential in Input/Output operations & processing, exceptions, and mutability of state. Anything else that may contribute to the varying probability of a function is also of concern, including language features such as NULL which, when passed in as arguments to a function can cause functions to stray from their guarantee of reliability and robustness. 

This is all particular to computation within a function, with the ideal function being one that is so-called 'pure'. 

Ensuring reliability

  • Preventing functions throwing any exceptions
  • Preventing arguments being invalid such as NULL (see smart constructors that validate on construction)
  • Writing pure functions
  • Isolating I/O to 'the fringes'

Using Higher-Ordered Functions

A distinctive trait of functional programming is the casual manner in which functions are passed into other functions. Functional programming treats functions as first-class citizens, in so much as they can be passed as functions.

In Lambda calculus, this notion is represented by the concept of abstractions and applications. (Dudak 1989)

Immutability of program state

A central concept in functional programming is reliability. Modifying state after the fact, during or before processing can impair a function's guarantee to be reliable.

In much the same way that exceptions and I/O may produce different results irrespective of whether the same function input arguments if those arguments themselves are changed during the processing by the function, it's not clear or guaranteed that the impact of the function has not invalidated state.

Arguments that are used or depended on outside the function should not be modified during the function execution.

The practical way to achieve this is to make any modifications on any data non-referencable by any other code, other than the function in which it was modified, that is to to make an exclusive copy of any data arguments that are passed in and modify that. In so doing it makes it impossible for other code that originally had access to the data that was passed in as arguments, to modify that data after the function exits(and thus invalidate any guarantee the function makes).

This relies on copying data, releasing it, and ensuring it cannot be modified after it leaves the function. Other options are listed below.

Ensuring immutability of data

  • Copying argument data if it is not immutable.
  • Immutable data types could negate the need to copy as they could not change after the function executes, without creating a new copy.
    • Creating your own immutable types - such as classes with smart constructors and get only accessors etc.
    • Using existing C# immutable data types
  • Assignment statements are scrutinised (no assignment to global state incl. instance members and other non-local state)
  • Member functions that act on a class's data either do not do this or are converted to static functions that thus explicitly cannot.

Declarative style or organisation of computation

Functional Programming techniques

In my view, techniques are ways, aspects or methods that bring about the foundational paradigms: reliability and higher-ordered functions.

Any means in which to achieve this, I consider to be techniques, such as ensuring immutability. These are based on decisions the programmer makes to achieve these.

This might include using language dependant attributes like immutable data types, or external libraries such as LanguageExt. This might include removing NULLs by utilizing Option<T> or removing the throwing of exceptions through Try<T> etc.

Techniques 

  • Using immutable data types 
    • Immutable Dictionaries, Tuples
  • Copying data
  • Not throwing exceptions or implementing a means to suppress exceptions (Try<> and Ensure) into a standardised form such as a failure return type.
  • Encapsulating failures in return types such as using Either<Failure,R> to maintain the reliability of function always returning uniformly despite exceptions, I/O problems etc.
  • Converting functions into pure functions
    • Moving functions to be static
    • Removing access to instance variables
    • Removal of operating on non-local data, mutable types (such as copying it first to make it local
  • Pipelining(including Binding() and Mapping()) to declaratively construct logic blocks using Monads and Functors
  • Using smart constructors
  • Implementing and designing to deal with I/O in an isolated way or pushing to the fringes design 

Distinct Benefits of Functional Programming In General

Functional programming is only as useful as its benefits. Reliability being the most crucial in my opinion. Others are listed below.

  • Reliability (Immutability, function guarantee etc)
  • Parallelism (Immutability)
  • More expressive formation of logic (declarative)
  • Conciseness codebase (declarative)
    • "shorter programs tend to have fewer bugs"15
  • Lazy evaluation through HOFs (only execute if the condition is met)

Distinct Specific techniques of Functional Programming In General

Also, specific techniques are useful in trying to obtain the ideals of reliability too:

  • Lazy evaluation of transforming functions and Short-circuiting (Monads in general)
    • Lazy evaluation through HOFs (only execute if the condition is met - see Binding and Mapping for data extraction)
  • No exception handlers (Try<T>, Either<L,R> and Ensure(), EnsuringBind() etc)
  • Removal of NULL (Option<T>)
  • Using Bind() on and Either<> removes requiring to write repetitious/builder-plate If..else code for Left or Right circumstances
  • Reasoning about contents of variables is easier (Option<T> has no NULL), Either<L,R> will only allow for two outcomes in the type
  • The non-happy path is always accounted for with Option<T> or Either<L,R> when extracting values using Match()
  • Memoization and caching

In many ways, I think functional programming as it's used in programming these days, especially in industry (read: business) is a mix of what is purely functional ideas such as those introduced through lambda calculus, including strict immutability and those that are inherently not but which are required in order to be particularly productive in the mainstream of imperative programming: sequential state change, exception handling, NULLs, mutable datatypes. 

I'm trying to rewrite a game prototype I wrote for my Game Architecture course to implement these ideal.

Ruby RSpec let and let! diffirences

Details
Category: Code
By Stuart Mathews
Stuart Mathews
08.Jul
08 July 2020
Last Updated: 08 July 2020
Hits: 5552
  • Ruby

An interesting question came up today in a code review around using let and let! in Rspec in ruby. When do you use which and why?

Its answered briefly and very concisely here as this:

Use let to define a memoized helper method. The value will be cached
across multiple calls in the same example but not across examples.

Note that let is lazy-evaluated: it is not evaluated until the first time
the method it defines is invoked. You can use let! to force the method's
invocation before each example.

but maybe it's a little too concise and needs a bit of unfolding...

Firstly. a few facts:

  1. both let and let! variables are reset between example runs
  2. Within the same example. both let and let! re-use and thus cache the value of the defining code block that makes up the definition (intra-example)
  3. only let! will re-evaluate its value immediately before a new example, while a let will wait until it's first encountered in the example, before re-evaluating/re-determining its value.

With a let! variable you're basically saying that before it's ever first even used in any example, first explicitly run its defining block before the start of the example ie evaluate its value. Then, this resulting value will be used as its value within the example (and it will remain unchanged within the example, ie it will be cached intra-example)

Otherwise, with let, as soon as the let variable is encountered for the first time in the example(it's lazy-evaluated), only then will it be evaluated, and then re-used, without re-evaluation(much like let!) ie cached throughout the example.

An example for let! being useful would be if during the execution of an example(before the let variable is evaluated because it's not used yet), the example code goes and invalidates data that the let variable ordinarily depends on. Later on, when the let variables is encountered for the first time, it is then evaluated and uses now invalid data it depended on). This now sets the let variable to data that would not have existed in this way prior to having the example started/run.

Had the let variable been evaluated before the example had gone ahead and invalided its dependent data, ie it was pre-evaluated before the example (ie if it was declared with let! instead), it would not pick up the new(erroneous?) changes to the dependant data.

This is particularly true if the dependant data is a shared database modified throughout the example and then which affects the fist-time evaluation(lazy-evaluated) of a let variable:

Valid instances of let! might be:

let!(:country) { Country.where(code: 'US').first }

where the contents of the database's Country has changes made to it throughout the example, but you want the first country to be the first country at the time the example started, not when the :country variable is first evaluated i.e when the example gets to it in the code (as it might have changed since then in the database).

Generally speaking, you should use let when if the variable does not depend on any data that will change during the lifetime of the example:

let!(:customer) { FactoryGirl.create(:customer) }

Otherwise using let by default is usually enough

More Articles …

  1. Convolution, Running and Finite State Machines
  2. LanguageExt tutorial, games and timing
  3. Lambda Cross Account access with Serverless framework
  4. Mostly copies of itself
  5. Bind behind the scenes
  6. Using Language Ext
  7. Pure functions
  8. Complex or Elaborate
  9. Nullable checking in the Wild-West
  10. Understanding how the Linq query syntax works

Subcategories

Game Development Article Count:  28

I discovered the realms of game development purely by accident, having picked up a book entitled 'Core Techniques and Algorithms in Game Programming' and discovered a surprising niche of innovation in programming quite unparalleled to my day-to-day needs as a developer. Here optimisation, graphics rendering, and algorithms are used on a totally different level and its very interesting.

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

Page 3 of 17