Yes, interesting. I clicked on the demo lots of times, and the algorithm becomes obvious, but that hakmem175 isn’t. I’ll study it one day.
OK, well I managed to spend a bit of time on this, but haven’t made a great deal of progress, and what I have done might be a backwards step!
I’ve merged the two sketches from @Chrisir, and used the function from @RichardDL that calculates 3 bits-on numbers…
// list uses gray scales as index. The list contains the
//different permuts for this gray scale (number of permuts can vary).
ListOfPermuts[] permuts = new ListOfPermuts[256];
PixelRepresentation[][] myList;
IntList myBinaryList;
int binaryListLength;
int num;
int count3 = 0;
PImage img;
void setup() {
size(600, 600);
noSmooth();
noStroke();
//frameRate(1);
img = loadImage("fashion_MNist_01.png");
img.resize (200, 200);
myList = new PixelRepresentation[img.width][img.height];
myBinaryList = new IntList();
// RichardDL's code for finding 12 bit binary numbers with 3 bits ON
for (num = 0; num < 4096; num++) {
if (is3bits(num)) {
count3++;
myBinaryList.append(num);
}
}
// fill permuts
// i represents gray value
for (int i=0; i<256; i++) {
permuts[i] = new ListOfPermuts( i );
}//for
for (int x = 0; x < img.width; x++) {
for (int y = 0; y < img.height; y++ ) {
// Calculate the 1D pixel location
int loc = x + y*img.width;
color c1=img.pixels[loc];
myList[x][y] = new PixelRepresentation (c1, x*5, y*5);
}// for
}// for
}// setup
void draw() {
//image(img, 10, 10);
color c1 = get(mouseX, mouseY);
for (int x = 0; x < img.width; x++) {
for (int y = 0; y < img.height; y++ ) {
myList[x][y].display();
}// for
}// for
permuts[int(brightness(c1))].display();
}// draw
// ================================================================
class PixelRepresentation {
//
color col;
float x, y;
boolean[][] fieldArray = new boolean [ 4 ][ 3 ]; // !!!!!!!!!!!!
PixelRepresentation (color col_,
float x_, float y_) {
col=col_;
x=x_;
y=y_;
}
void display() {
// use fieldArray here
fill(col);
rect(x, y, 3, 3 );
}
}//class
//
//================================================================
class ListOfPermuts {
// class holds all permutations for ONE brighntness
// length can vary (therefore ArrayList)
ArrayList<Field> listOfPermutations = new ArrayList();
int brightnessOfField;
// counter or permut for display as an animation
int permutNum;
//constr
ListOfPermuts (int brightnessOfField_) {
brightnessOfField =
brightnessOfField_;
// random number of permuts for this brightness.....
// replace by something that gives the permuts for the brightnessOfField_
binaryListLength = myBinaryList.size();
for (int i = 1; i < binaryListLength; i++) {
Field f1 = new Field(brightnessOfField);
listOfPermutations.add(f1);
} //for
} // constr ---------
void display() {
int xoffset = 330;
int yoffset = 300;
// make a horizontal list
for (Field f1 : listOfPermutations) {
f1.display(xoffset, yoffset);
xoffset += 40;
}//for
// Animation
Field f1 = listOfPermutations.get(permutNum%listOfPermutations.size());
f1.display(330, height-139);
permutNum++;
//
} // func
//
} //class
//================================================================
class Field {
// ONE 3x4 Field
boolean [][] field = new boolean [3][4];
//constr
Field (int brightnessOfField_) {
// replace by something that gives the permuts for the brightnessOfField_
for (int x = 0; x < field.length; x++) {
for (int y = 0; y < field[0].length; y++ ) {
field[x][y] = false;
int position = x + (y * field.length);
// bitwise trick to iterate over binary digits
int onOrOff = ((myBinaryList.get(0) & 1<<position) >> position);
if (onOrOff > 0)
field[x][y] = true;
}
}
}//constr ---------
void display( int xoffset, int yoffset) {
//
for (int x = 0; x < field.length; x++) {
for (int y = 0; y < field[0].length; y++ ) {
//
fill(0);
if (field[x][y]) fill(255); // WHITE
rect(xoffset + x*5, yoffset + y*5, 4, 4);
}
}
}//func
//
}//class
//
// ================================================================
// RichardDL's code for finding 12 bit binary numbers with 3 bits ON - function
boolean is3bits(int no)
{
// return true if given number has 3 bits set.
int ix;
int tot = 0;
for (ix = 0; ix < 12; ix++) {
if ((no & 1) == 1) tot++;
no = no >> 1;
}
return tot == 3;
}
I am now able to fill the Field object with correct numbers for 3-bits-on, but am filling it with only ONE configuration over and over… I realise this is because I am just using the ‘0
th’ item in myBinaryList
, but I’m not quite sure what to do to add ALL 220 items in myBinaryList
here…
int onOrOff = ((myBinaryList.get(0) & 1<<position) >> position);
I’ll try and break my code down and explain it a bit better tomorrow, but for now, I’m screened out!
Hello,
You are almost there I think.
I don’t understand this code by @RichardDL ; therefore I have difficulties to help:
// RichardDL's code for finding 12 bit binary numbers with 3 bits ON
for (num = 0; num < 4096; num++) {
if (is3bits(num)) {
count3++;
myBinaryList.append(num);
}
}
Does this make all patterns for ONE gray scale? I don’t understand.
In my code
In my code, I assume you have a list “permuts” that holds for each gray scale ALL the permuts (in the class “ListOfPermuts
”.
Therefore you’d say:
in the constr of class “ListOfPermuts
” loop over all the patterns in myBinaryList (but only for the current gray scale!!! So the myBinaryList must be made new within the for loop in draw???
This is the for loop I am referring to
// fill permuts
// i represents gray value
for (int i=0; i<256; i++) {
// make new myBinaryList here?
permuts[i] = new ListOfPermuts( i ); // constr uses myBinaryList?
}//for
)
and then in the constr I mentioned:
binaryListLength = myBinaryList.size();
for (int i = 1; i < binaryListLength; i++) {
println(myBinaryList.get(i));
// USE myBinaryList here !!!!
Field f1 = new Field( myBinaryList.get(i) ); // but in the constr of class Field I don't know how to get the bits from the int?
listOfPermutations.add(f1);
} //for
but in the constr of class Field I don’t know how to get the bits from the int to make the pattern
One fault
One fault (I think): my bad.
PixelRepresentation carries
boolean[][] fieldArray = new boolean [ 4 ][ 3 ]; // !!! should be 3 4
as part of representing an image
but class Field also has this
as part of representing permutations.
Chrisir
I did something similar with arduino and a led matrixBicolor,
I create 3x4 in hexa to display my font.
maybe it can help : bicolorMatrix on youtube
the code : bicolor on github
Hi @Chrisir - thanks again for your help - I REALLY appreciate it - but I think I’ve got myself into a bit of a mess.
The problem is I don’t really understand exactly what your code as doing - my fault!
I will try to work through it and answer your questions, but right now I feel out of my depth…
MY problem is that I don’t really understand what @RichardDL 's code is doing!
Is it making the patterns for ONE gray scale (which one, 12??) or for all?
I suggested to make the result of brightness(fromPixel) to int to get 0 to 255 as a result.
Then we would need 256 different sets of patterns.
My approach
My approach is simple:
First Line of thought
PixelRepresentation[][] myList;
holds the image as patterns (2D array)PixelRepresentation
contains a 2D array of the pattern (probably this is unnecessary because we have ListOfPermuts)
The 2nd Line of thought
ListOfPermuts[] permuts
holds a 256 long list (one for eachint(brightness())
)- ListOfPermuts holds an
ArrayList
to hold the patterns for each brightness (different numbers)
The 3rd Line of thought
- To bring this together, we for loop-for loop over the image and fill
PixelRepresentation[][] myList;
with brightnesses - We fill
ListOfPermuts[] permuts
with permuts for each brightness - We display myList which uses the permuts with its brightness and animates over the patterns in its ArrayList
I hope this helps!
Chrisir
Thanks for sticking with me @Chrisir!
For the moment, I won’t use RichardDL’s code - it only gives values for 3 pixels on in a 12-pixel grid, and we need ALL permutations for ALL ‘numbers of pixels on’.
I wrote some python code which generates all this data - so I think I should use that for now.
Yes, this makes sense - but because (for a 12-pixel matrix) there are 256 greyscale levels but only 12 pixels, so the number of ‘actual’ grayscale values will be 256/12 ≈ 21.
Thanks for your breakdown above. I’ve got the weekend free, so I hope to get to grips with it!
Here’s an image fo how I see it… Have I got the hierarchy right?
Maybe you could restate your problem / goal.
What, concretely are you trying to produce as output? A single grid of boxes, of arbitrary dimensions, that represents a 255 brightness value?
And then you want to display that one single grid on the screen – e.g. the whole sketch canvas taken up by a single 8x8 grid of rectangles, with 64 values, representing a 0-255 brightness?
And then you want to animate it by permutations for that one pixel that you are measuring? So the pixel is 101/255, so you round that to 25 and permute 25 bright boxes across a grid of 64 boxes?
Is that right?
What happens once you have animated through all the permutations of that one pixel? Do you move on to the next pixel in the image and start over?
Thanks for your request to restate/clarify my problem. @Chrisir has given code that solves the problem I posed, and explained it very well, however, I have not been able to fully understand what the code is doing - my fault - I’m just not that familiar with using classes and arrays and constructors to really understand how I can modify it.
This is what I would like to do:
generatePermutations.py [gist]
I haven’t really been able get to grips with @Chrisir’s code, although I know it shows me a better way to represent my data using classes, and it solves most of my problems.
What I’d like to ask @Chrisir is if you could show me how to join your two pieces of code, and how I can ‘add’ my data into the code to fill the listOfPermuts…
If we could just go one step at at time?
Almost there.
When you have all permuts: Are these of one brightness? or of how many?
can you post either your permut py sketch as processing sketch here or the results?
As I mentioned a few times and didn’t get ANY answer from you: What is Richard’s code doing and for which gray scales?
I mean he provides 220 permuts but how to tell which to use for the brightness?
Are you okay when instead of 256 brightness steps we just work with / or so?
got it I think
press any key to toggle between two views:
- debug view to see all permuts
- real view of animated graphic
Explanation
the 3x4 grid holds 12 bits, 4096 permutations.
The number of bits that are 1 decide the brightness of the 3x4 grid. If more bits are ON, the grid appears more bright. So there are 12 levels of brightness.
Therefore I use these 12 brightness instead of 256 levels of brightness/gray scales. I use map() command to change from 255 to 12 scale.
The 12 brightnesses each have a different number of permuts (the different grids), between 1 and 220 different grids.
The animation loops between the different grids
I hope this helps.
Chrisir
// list uses gray scales as index. The list contains the
//different permuts for this gray scale (number of permuts can vary).
ListOfPermuts[] permuts = new ListOfPermuts[256]; // ONLY 12 used !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
PixelRepresentation[][] myList; // image !!!!!!!!
PImage img;
int state = 1;
void setup() {
size(1900, 800);
background(0) ;
noSmooth();
noStroke();
frameRate(13);
img = loadImage("process1.png"); // "fashion_MNist_01.png");
img.resize (200, 200);
// fill image grid
myList = new PixelRepresentation[img.width][img.height];
// fill permuts
for (int i=0; i<256; i++) {
permuts[i] = new ListOfPermuts( i );
}//for
fillpermuts () ;
for (int x = 0; x < img.width; x++) {
for (int y = 0; y < img.height; y++ ) {
// Calculate the 1D pixel location
int loc = x + y*img.width;
color c1=img.pixels[loc];
myList[x][y] = new PixelRepresentation (c1, x*5, y*5);
}// for
}// for
}// setup
void draw() {
background(0) ;
switch(state) {
case 0:
for (int x = 0; x < img.width; x++) {
for (int y = 0; y < img.height; y++ ) {
myList[x][y].display();
}// for
}// for
break;
case 1:
// for debug / press any key to toggle
background(111);
for (int i=0; i<256; i++) {
fill(0);
text(i+" "+permuts[i].listOfPermutations.size(),
17, i*20+22);
fill(255);
text("Permutations Overview.\nTable shows number of gray scale and the number of permutations for that number and the permuts as pixels. \nHit any key to toggly view",
140, 299);
permuts[i].displayLong(i);
}
break;
}//switch
}// draw
// ----------------------------------------------------------------
void keyPressed() {
//toggle
if (state==0)
state=1;
else
state=0;
}
// ----------------------------------------------------------------
void fillpermuts () {
// solution by RichardDL
int num;
int count3 = 0;
for (num = 0; num < 4096; num++) {
// RUN ALWAYS, the if is not working / is always true
//if (true||is3bits(num)) {
count3++;
// println(String.format("%4d %s %4d", num, binary(num, 12), count3), count(num) );
// println(count(num));
permuts[count(num)].listOfPermutations.add ( new Field ( binary(num, 12) ));
//}//if
}//for
//
}
// ================================================================
class PixelRepresentation {
// represents the entire image
color col;
float x, y;
int brightnessOnScale12 ;
PixelRepresentation (color col_,
float x_, float y_) {
col=col_;
brightnessOnScale12 = int(map(brightness(col), 0, 255, 0, 12));
x=x_;
y=y_;
}
void display() {
permuts[brightnessOnScale12].display(x, y);
}
}//class
//
//================================================================
class ListOfPermuts {
// class holds all permutations for ONE brighntness
// length can vary (therefore ArrayList)
ArrayList<Field> listOfPermutations = new ArrayList();
// counter or permut for display as an animation
int permutNum;
//constr
ListOfPermuts (int brightnessOfField_) {
//
} // constr ---------
void display(float x_, float y_) {
// Animation
Field f1 = listOfPermutations.get(permutNum%listOfPermutations.size());
f1.display(x_, y_);
permutNum++;
//
} // func
void displayLong(int i_) {
int xoffset = 70;
int yoffset = i_*20+20;
// make a horizontal list - just to get an overview
for (Field f1 : listOfPermutations) {
f1.display(xoffset, yoffset);
xoffset += 20;
}//for
}//method
//
} //class
//================================================================
class Field {
// ONE 3x4 Field
boolean [][] field = new boolean [3][4];
//constr
Field(String s1_) {
// reads a String: binary data
int counter=0;
//
for (int x = 0; x < field.length; x++) {
for (int y = 0; y < field[0].length; y++ ) {
field[x][y] = false;
if (s1_.charAt(counter)=='1') {
field[x][y] = true;
}
counter++;
}
}
}//constr
void display( float xoffset, float yoffset) {
//
for (int x = 0; x < field.length; x++) {
for (int y = 0; y < field[0].length; y++ ) {
//
fill(0);
stroke(0);
if (field[x][y]) {
fill(255); // WHITE
stroke(255);
}
//rect(xoffset + x*5, yoffset + y*5, 4, 4);
point(xoffset +x, yoffset + y);
}
}
}//func
//
}//class
// ================================================================
// RichardDL's code for finding 12 bit binary numbers with 3 bits ON - function
//boolean is3bits(int no)
//{
// // return true if given number has 3 bits set.
// int ix;
// int tot = 0;
// for (ix = 0; ix < 12; ix++) {
// if ((no & 1) == 1) tot++;
// no = no >> 1;
// }
// return tot == 3;
//}
int count(int no)
{
// return from given number the bits set Number
int ix;
int tot = 0;
for (ix = 0; ix < 12; ix++)
{
if ((no & 1) == 1) {
tot++;
}
no = no >> 1;
}
return tot ;
}
@Chrisir - you are amazing - and your solution is beautiful:
VIDEO:
https://youtu.be/2_eleGCoSwE
HUGE thanks to all who have helped on this - @Chrisir @RichardDL @jeremydouglass @glv
This has been part of a personal project I have been working on during the COVID-19 lockdown using LCD Character Displays… a couple of images here:
VIDEO:
(https://www.youtube.com/watch?v=vbP9f3YmiEs)
However - I can not call this project my own until I can reproduce what @Chrisir et-al have done. That is my task on-going, and you have given me all the clues I need to do so. Thank you!
Hello,
How cool is that hardware! I may contact you to discuss…
If you can find an investor consider replacing those LCDs with OLEDs. Better viewing angles and great in light and the dark! I have done this for a few high profile projects.
You will be able to code this from scratch! Glean insight where needed and make it your own.
I liked Richards approach to finding bits.
What is communicating with the LCDs?
I see permutations used a lot in this topic; it should be combinations.
Too many permutations!
Permutation Calculator
Combination Calculator
:)
Thank you for your kind words, was a pleasure to work with you.
Warm regards,
Chrisir
P.S.
When you look at setup() again
void setup() {
size(1900, 800);
background(0) ;
noSmooth();
noStroke();
frameRate(13);
img = loadImage("process1.png"); // "fashion_MNist_01.png");
img.resize (200, 200);
// fill image grid
myList = new PixelRepresentation[img.width][img.height];
// fill permuts
for (int i=0; i<256; i++) {
permuts[i] = new ListOfPermuts( i );
}//for
fillpermuts () ;
for (int x = 0; x < img.width; x++) {
for (int y = 0; y < img.height; y++ ) {
// Calculate the 1D pixel location
int loc = x + y*img.width;
color c1=img.pixels[loc];
myList[x][y] = new PixelRepresentation (c1, x*5, y*5);
}// for
}// for
}// setup
from an aesthetically point of view:
the parts concerning
- image, img and PixelRepresentation (it’s for image) should be one section,
- and only after that the section with permuts;
so better version:
void setup() {
size(1900, 800);
background(0) ;
noSmooth();
noStroke();
frameRate(13);
// load image
img = loadImage("process1.png"); // "fashion_MNist_01.png");
img.resize (200, 200);
// prepare and fill image grid "myList"
myList = new PixelRepresentation[img.width][img.height];
for (int x = 0; x < img.width; x++) {
for (int y = 0; y < img.height; y++ ) {
// Calculate the 1D pixel location
int loc = x + y*img.width;
// get color
color c1 = img.pixels[loc];
// store color and future position
myList[x][y] = new PixelRepresentation (c1, x*5, y*5);
}// for
}// for
// prepare and fill permuts
for (int i=0; i<256; i++) {
permuts[i] = new ListOfPermuts( i );
}//for
fillpermuts () ;
}// setup
Remark
Also I made the function int count(int no)
which is a variation of Richard’s is3bits()
.
It counts how many 1’s there are in a bit pattern thus determine also its brightness (from 0 to 12).
I use this an index for permuts[] array.
When retrieving data from permuts I map (use map() command) the brightness from 0…255 to 1…12 to use this as an index for permuts[].
Remark
Since binary()
gives you the bit pattern as a String (length 12) I use this (with charAt()
) to fill the 3x4 fields representing the patterns for each pixel.