dwalton76 / rubiks-cube-tracker

Given an image of a rubiks cube, find the RGB value for each square.
MIT License
130 stars 37 forks source link

AttributeError: 'RubiksImage' object has no attribute 'get_black_border_width' #10

Closed CptDangerous closed 1 year ago

CptDangerous commented 1 year ago

I'm having a nightmare trying to get my EV3/BrickPi3 Rubik's cube solver robot to work after having to re-install the software from scratch (SD card threw in the towel and no back-up image!)

Running BricKuber.py the message I was getting yesterday was as follows:

Taking pictures of each face, and determining cube configuration.
START: Read Face Colors: top
Picture taken
Failed in processing image: 2022-10-04 20:11:36,396            __init__.py     INFO: Analyze /tmp/BricKuber_top_face.jpg
Traceback (most recent call last):
  File "/usr/local/bin/rubiks-cube-tracker.py", line 56, in <module>
    rimg.analyze_file(args.filename)
  File "/usr/local/lib/python3.7/dist-packages/rubikscubetracker/__init__.py", line 1685, in analyze_file
    return self.analyze(webcam=False, cube_size=cube_size)
  File "/usr/local/lib/python3.7/dist-packages/rubikscubetracker/__init__.py", line 1531, in analyze
    self.get_black_border_width(webcam)
File "/usr/local/lib/python3.7/dist-packages/rubikscubetracker/__init__.py", line 1134, in 
get_black_border_width
         ), f"black_border_width  {self.black_border_width},  median_square_width  {self.median_square_width}"
 AssertionError: black_border_width 94,  median_square_width 39

which to my untutored eye seemed to be saying that the black border was wider than the detected square.

I left it at that for the rest of the day and came back to the problem this evening. I printed out the whole of 'init.py' in an attempt to trace the flow through the code. Much to my surprise, when I ran BricKuber.py again I got a different error:

Taking pictures of each face, and determining cube configuration.
START: Read Face Colors: top
Picture taken
Failed in processing image: 2022-10-04 20:11:36,396            __init__.py     INFO: Analyze /tmp/BricKuber_top_face.jpg
Traceback (most recent call last):
  File "/usr/local/bin/rubiks-cube-tracker.py", line 56, in <module>
    rimg.analyze_file(args.filename)
  File "/usr/local/lib/python3.7/dist-packages/rubikscubetracker/__init__.py", line 1685, in analyze_file
    return self.analyze(webcam=False, cube_size=cube_size)
  File "/usr/local/lib/python3.7/dist-packages/rubikscubetracker/__init__.py", line 1531, in analyze
    self.get_black_border_width(webcam)
AttributeError: 'RubiksImage' object has no attribute 'get_black_border_width'

As far as I'm aware I haven't altered the code in any way nor reinstalled any packages but the Class RubiksImage has no attribute 'get_black_border_width'

Please can you throw any light on this puzzle?

dwalton76 commented 1 year ago

So the first one

AssertionError: black_border_width 94, median_square_width 39

basically this is a scanning error that will likely go away if you try it again. Various lighting conditions can lead to this...things like glare on the cube from a bright light, or if it is too dark, etc. Long term I should really move to using machine learning to locate the cube in the picture I just haven't gotten around to it.

This one is more mysterious

File "/usr/local/bin/rubiks-cube-tracker.py", line 56, in
rimg.analyze_file(args.filename)
File "/usr/local/lib/python3.7/dist-packages/rubikscubetracker/init.py", line 1685, in analyze_file
return self.analyze(webcam=False, cube_size=cube_size)
File "/usr/local/lib/python3.7/dist-packages/rubikscubetracker/init.py", line 1531, in analyze
self.get_black_border_width(webcam)
AttributeError: 'RubiksImage' object has no attribute 'get_black_border_width'

Because that method is there in the latest code: https://github.com/dwalton76/rubiks-cube-tracker/blob/master/rubikscubetracker/__init__.py#L1099

so maybe you have an older version installed? I would remove the current install and re-install like so:

sudo rm -rf /usr/local/lib/python3.7/dist-packages/rubikscubetracker/
sudo rm /usr/local/bin/rubiks-cube-tracker.py
sudo pip install git+https://github.com/dwalton76/rubiks-cube-tracker.git
CptDangerous commented 1 year ago

Hi Daniel, thanks for the response. I noticed when I first built the robot (Jan 2019) that the amount and type of light (daylight or artificial) had an enormous effect on whether the software resolved the faces and hence found a solution.

The mystery is that between one boot yesterday and the next boot today the method disappeared. Maybe when I loaded the code into Geany today to print it I inadvertently removed that part. Who knows?

I followed your recommendation for reinstalling but now the /usr/local/bin/rubiks-cube-tracker.py is missing. Is that installed from a different .git?

Thanks again.

Chris (aka Cpt Dangerous)

CptDangerous commented 1 year ago

later:

In fact  /usr/local/lib/python3.7/dist-packages/rubikscubetracker/ failed to install! rubiksresolver/ is there.

even later:

OK, problem solved, I had to add --upgrade to the pip install to get the latest version (3.0.0) which seemed to be already know about:

Successfully built rubikscubetracker
Installing collected packages: rubikscubetracker
  Found existing installation: rubikscubetracker 3.0.0
    Uninstalling rubikscubetracker-3.0.0:
      Successfully uninstalled rubikscubetracker-3.0.0
Successfully installed rubikscubetracker-3.0.0

Thanks again.

Now I need to experiment with the lighting...

CptDangerous commented 1 year ago

I can't get beyond:

Failed in processing image: 2022-10-05 10:37:35,298 init.py INFO: Analyze /tmp/BricKuber_top_face.jpg

The image it's trying to analyze is:

BricKuber_top_face

Focus doesn't seem too great. I'm using a brand new Raspberry Pi camera V2 having managed to brick my old V1.3 somehow!

I wondered if it might help the processing if I put a matt black card below the cube table so there aren't any extraneous objects to filter out?

dwalton76 commented 1 year ago

I wondered if it might help the processing if I put a matt black card below the cube table so there aren't any extraneous objects to filter out that sounds like a good next step. Especially the part on the right side where you can see the motor...I wonder if that is confusing it somehow.

CptDangerous commented 1 year ago

OK, black card arrived this afternoon. Cut a sheet to cover the main part of the camera view so the image looked like:

BricKuber_top_face

but still got the error message:

Failed in processing image: 2022-10-07 16:16:54,547            __init__.py     INFO: Analyze /tmp/BricKuber_top_face.jpg

Where to go from here ...?

dwalton76 commented 1 year ago

If you can upload the images in /tmp/ here to this github issue I should be able to reproduce it and figure out what is going on.

CptDangerous commented 1 year ago

That is the image from /tmp/

Are you not able to download it?

dwalton76 commented 1 year ago

ah, I wasn't sure if that was the original or not. Will give it a try

CptDangerous commented 1 year ago

Yes, I pulled the image straight out of /tmp for the post. Good luck.

dwalton76 commented 1 year ago

@CptDangerous I have good news and bad news...the good news is I am able to process your image with the latest and greatest rubikscubetracker code. The bad news is that means you somehow have an older copy installed that you are using which fails to process the image above. Run the following to find and delete any copies you have installed

sudo find /usr -name rubikscubetracker | xargs rm -rf
sudo find /usr -name rubiks-cube-tracker.py | xargs rm -rf

Then run sudo pip install git+https://github.com/dwalton76/rubiks-cube-tracker.git to re-install it. Logout, log back in and then run rubiks-cube-tracker.py --filename cube.jpg where cube.jpg is the pic above. You should see this


$ rubiks-cube-tracker.py --filename cube.jpg 
2022-10-07 20:21:42,862            __init__.py     INFO: Analyze cube.jpg
{"1": [239, 122, 75], "2": [253, 247, 253], "3": [254, 254, 252], "4": [237, 119, 70], "5": [35, 82, 182], "6": [253, 253, 127], "7": [235, 113, 69], "8": [39, 81, 179], "9": [253, 174, 115]}
$
dwalton76 commented 1 year ago

PS If you want to see some debug images as to what the code is doing when it processes the image run rubiks-cube-tracker.py --filename cube.jpg --debug

CptDangerous commented 1 year ago

I hope you don't mind me contradicting you but I consider that to be all good news. I had come to the conclusion that there had to be something wrong with the installation of the software. It didn't go smoothly - I had a nightmare getting the right version of numpy that would satisfy all the dependancies so I was kind of expecting repercussions further down the line.

My wife and I have to go out and do a paper round for the local village shop where the owner has recently had a heart attack - not us reliving our misspent youths! I'll give your suggestions a try later this morning.

Many thanks for your attention to this.

Cheers

Chris

CptDangerous commented 1 year ago

OK, so here's a really strange thing. Running rubiks-cube-tracker.py --filename /tmp/BricKuber_top_face.jpg gets:

2022-10-08 10:50:40,495            __init__.py     INFO: Analyze /tmp/BricKuber_top_face.jpg
{"1": [236, 200, 41], "2": [251, 110, 58], "3": [242, 215, 202], "4": [220, 9, 43]}
(results are slightly different 'cos I had to run BricKuber.py again to get a new image of the same face)

However, running BricKuber.py and starting at the same face gets: Taking pictures of each face, and determining cube configuration.

START: Read Face Colors: top
Picture taken

Failed in processing image: 2022-10-08 10:52:22,616            __init__.py     INFO: Analyze /tmp/BricKuber_top_face.jpg

So, I'm inclined to think that something is wrong further up the food chain. I'm tempted to ditch the installation and start from scratch ... again. As I mentioned I had problems earlier installing numpy so that the version satisfied all dependencies.

Following your instructions above didn't go smoothly. The "sudo find/rm" sequence failed with 'Permission denied' despite the ownership being pi:pi

sudo find  /usr  -name  rubiks-cube-tracker.py | xargs rm  -rf
rm: cannot remove '/usr/local/bin/rubiks-cube-tracker.py': Permission denied

However:

ls -l /usr/local/bin/rubiks-cube-tracker.py
-rwxr-xr-x 1 pi pi 3056 Oct  8 10:30 /usr/local/bin/rubiks-cube-tracker.py

Once I'd removed the offending file(s) as root I still had to use --upgrade on the pip install command:

sudo pip install --upgrade git+https://github.com/dwalton76/rubiks-cube-tracker.git
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Collecting git+https://github.com/dwalton76/rubiks-cube-tracker.git
  Cloning https://github.com/dwalton76/rubiks-cube-tracker.git to /tmp/pip-req-build-8c_o3qhv
  Installing build dependencies ... done
Requirement already satisfied, skipping upgrade: opencv-python>=4.5 in /usr/local/lib/python3.7/dist-packages (from rubikscubetracker==3.0.0) (4.6.0.66)
Requirement already satisfied, skipping upgrade: numpy>=1.14.5; python_version >= "3.7" in /usr/local/lib/python3.7/dist-packages (from opencv-python>=4.5->rubikscubetracker==3.0.0) (1.21.6)
Building wheels for collected packages: rubikscubetracker
  Running setup.py bdist_wheel for rubikscubetracker ... done
  Stored in directory: /tmp/pip-ephem-wheel-cache-ypjkuaxo/wheels/83/ef/54/764e78cffe69f137e6be3f317be5164c4dedf8f39d83e02504
Successfully built rubikscubetracker
Installing collected packages: rubikscubetracker
Successfully installed rubikscubetracker-3.0.0

Otherwise I got:

sudo pip install git+https://github.com/dwalton76/rubiks-cube-tracker.git
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Collecting git+https://github.com/dwalton76/rubiks-cube-tracker.git
  Cloning https://github.com/dwalton76/rubiks-cube-tracker.git to /tmp/pip-req-build-e93lhhq6
  Installing build dependencies ... done
Requirement already satisfied (use --upgrade to upgrade): rubikscubetracker==3.0.0 from git+https://github.com/dwalton76/rubiks-cube-tracker.git in /usr/local/lib/python3.7/dist-packages
etc...

It feels to me like there is a basic problem with the installation which may require a fresh start rather than trying to track down the culprit. What say you?

BTW do you work late into the night or are you in a different time zone from me (BST)?

CptDangerous commented 1 year ago

I can reproduce the same output from rubiks-cube-tracker.py as you by resurrecting the original BricKuber_top_face.jpg from this thread.

dwalton76 commented 1 year ago

ok the fact that you have to do --upgrade means it didn't get removed beforehand. It sounds like the pi user does not have sudo permissions but you do have root access though so do this to remove the old installation

# login as root
su

# delete the old install
find /usr -name rubikscubetracker | xargs rm -rf
find /usr -name rubiks-cube-tracker.py | xargs rm -rf

# then make 100% sure they are gone
find /usr -name rubikscubetracker
find /usr -name rubiks-cube-tracker.py

# logout as root
exit 

After that does sudo pip install git+https://github.com/dwalton76/rubiks-cube-tracker.git work?

dwalton76 commented 1 year ago

BTW do you work late into the night or are you in a different time zone from me (BST)? I was just up late last night...I am on EST (southeast US)

CptDangerous commented 1 year ago

'fraid not!

...
Requirement already satisfied (use --upgrade to upgrade): rubikscubetracker==3.0.0 from git+https://github.com/dwalton76/rubiks-cube-tracker.git in /usr/local/lib/python3.7/dist-packages
...
CptDangerous commented 1 year ago

pi is a member of group su

sudo:x:27:pi  in /etc/group

I wondered if there was something odd about the ownership & permissions on /usr/local/bin but:

root@BricKuber:~# ls -ld /usr
drwxr-xr-x 11 root root 4096 Sep 22 03:13 /usr
root@BricKuber:~# ls -ld /usr/local
drwxr-xr-x 10 root root 4096 Sep 22 03:05 /usr/local
root@BricKuber:~# ls -ld /usr/local/bin
drwxr-xr-x 3 root root 4096 Oct  8 14:03 /usr/local/bin
root@BricKuber:~# ls -l /usr/local/bin
total 72
-rwxr-xr-x 1 pi pi   219 Sep 28 22:50 f2py
-rwxr-xr-x 1 pi pi   219 Sep 28 22:50 f2py3
-rwxr-xr-x 1 pi pi   219 Sep 28 22:50 f2py3.7
-rwxr-xr-x 1 pi pi   344 Sep 30 12:06 fileswith
-rwxr-xr-x 1 pi pi   218 Sep 28 20:12 futurize
-rwxr-xr-x 1 pi pi 32780 Sep 28 20:03 gpio
-rwxr-xr-x 1 pi pi   223 Sep 28 20:12 kociemba
-rwxr-xr-x 1 pi pi   220 Sep 28 20:12 pasteurize
drwxr-xr-x 2 pi pi  4096 Oct  8 10:49 __pycache__
-rwxrwxrwx 1 pi pi   263 Sep 28 20:12 rubiks-color-resolver.py

looks OK to me.

In the words of an old Carson Robison talking blues: "There's something cockeyed somewhere."

dwalton76 commented 1 year ago

Can you post the output from these commands (you will need to be root or use sudo for the second one)

pip --version
ls  /usr/local/lib/python3.7/dist-packages | grep rubiks

Also regarding the red X in your comment above, you can use ``` to start and end a block of pre-formatted text (I edited your comment above to add those).

CptDangerous commented 1 year ago
pip 18.1 from /usr/lib/python3/dist-packages/pip (python 3.7)

rubikscolorresolver
rubikscolorresolver-1.0.0.dist-info
rubikscubetracker-3.0.0.dist-info
dwalton76 commented 1 year ago

ok pip looks good.

ah I did not think about the dist-info directory, that is what is causing the confusion. As root do rm -rf /usr/local/lib/python3.7/dist-packages/rubikscubetracker-3.0.0.dist-info and then install via sudo pip install git+https://github.com/dwalton76/rubiks-cube-tracker.git

CptDangerous commented 1 year ago

I was fascinated to see the various stages of analysis of the cube face output by rubiks-cube-tracker.py

OK, appeared to work:

pi@BricKuber:~ $ sudo pip install git+https://github.com/dwalton76/rubiks-cube-tracker.git
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Collecting git+https://github.com/dwalton76/rubiks-cube-tracker.git
  Cloning https://github.com/dwalton76/rubiks-cube-tracker.git to /tmp/pip-req-build-qis__76o
  Installing build dependencies ... done
Requirement already satisfied: opencv-python>=4.5 in /usr/local/lib/python3.7/dist-packages (from rubikscubetracker==3.0.0) (4.6.0.66)
Requirement already satisfied: numpy>=1.14.5; python_version >= "3.7" in /usr/local/lib/python3.7/dist-packages (from opencv-python>=4.5->rubikscubetracker==3.0.0) (1.21.6)
Building wheels for collected packages: rubikscubetracker
  Running setup.py bdist_wheel for rubikscubetracker ... done
  Stored in directory: /tmp/pip-ephem-wheel-cache-95r79jt8/wheels/83/ef/54/764e78cffe69f137e6be3f317be5164c4dedf8f39d83e02504
Successfully built rubikscubetracker
Installing collected packages: rubikscubetracker
Successfully installed rubikscubetracker-3.0.0
CptDangerous commented 1 year ago

... but:

Taking pictures of each face, and determining cube configuration.
START: Read Face Colors: top
Picture taken
Failed in processing image: 2022-10-08 14:52:53,531            __init__.py     INFO: Analyze /tmp/BricKuber_top_face.jpg
dwalton76 commented 1 year ago

can you post the /tmp/BricKuber_top_face.jpg that failed

CptDangerous commented 1 year ago

It's the same as the one I posted above but a new scan:

BricKuber_top_face-1

I have to drop this for today. We are about to go out for the evening. Thanks for your help.

dwalton76 commented 1 year ago

That one works fine for me

$ ./usr/bin/rubiks-cube-tracker.py --filename cube3.jpg 
2022-10-08 12:16:14,872            __init__.py     INFO: Analyze cube3.jpg
{"1": [234, 126, 92], "2": [253, 246, 253], "3": [253, 254, 252], "4": [232, 123, 89], "5": [34, 87, 189], "6": [253, 252, 159], "7": [230, 118, 87], "8": [37, 85, 185], "9": [253, 172, 131]}
$ 

This output though:

Taking pictures of each face, and determining cube configuration.
START: Read Face Colors: top
Picture taken
Failed in processing image: 2022-10-08 14:52:53,531            __init__.py     INFO: Analyze /tmp/BricKuber_top_face

That isn't coming from the rubikscubetracker code. Can you point me to the code you are running that is using rubikscubetracker?

dwalton76 commented 1 year ago

oh I see that is coming from https://github.com/DexterInd/BrickPi3/blob/master/Projects/BricKuber/brickuber_lib.py#L284-L291

The line that does if raw_result.stderr == '': that needs to be if raw_result.exit_code == 0

CptDangerous commented 1 year ago

Good morning.

Thanks for the suggestion. Changing:

        if raw_result.stderr == '':

to:

        if raw_result.exit_code == 0:

gets me:

Picture taken
Error: 'CompletedProcess' object has no attribute 'exit_code'

However:

if raw_result.returncode == 0:

gets a little further but falls over with:

Picture taken
Error: list index out of range

which is a familiar error message from the previous incarnation of this project. This is generated further down the line at:

            raw_result = raw_result.split("\n{")[1]

which is Dexter's code.

Once again many thanks for all your help. It looks like I need to post something on the DexterIndustries forum.

Later:

I commented out the line above and the program continued taking photos of each face until:

['rubiks-color-resolver.py', '--rgb', '\'{"1": [49, 123, 46], "2": [253, 242, 251], "3": [84, 170, 68], "4": [235, 120, 78], "5": [217, 54, 68], "6": [254, 255, 253], "7": [237, 216, 98], "8": [213, 51, 66], "9": [231, 67, 88], "10": [88, 177, 85], "11": [253, 255, 252], "12": [235, 80, 110], "13": [253, 248, 253], "14": [222, 61, 81], "15": [218, 61, 82], "16": [48, 135, 64], "17": [240, 136, 98], "18": [241, 224, 121], "19": [45, 117, 52], "20": [51, 140, 62], "21": [253, 243, 151], "22": [183, 35, 47], "23": [54, 146, 67], "24": [253, 247, 152], "25": [172, 29, 38], "26": [252, 241, 253], "27": [253, 245, 154], "28": [253, 145, 74], "29": [23, 76, 154], "30": [11, 57, 129], "31": [253, 152, 81], "32": [253, 123, 59], "33": [205, 6, 34], "34": [127, 194, 45], "35": [253, 240, 56], "36": [251, 232, 217], "37": [253, 254, 252], "38": [253, 253, 168], "39": [253, 175, 137], "40": [253, 247, 253], "41": [35, 88, 192], "42": [41, 89, 191], "43": [234, 127, 96], "44": [232, 125, 95], "45": [230, 120, 92], "46": [102, 152, 19], "47": [253, 79, 53], "48": [253, 90, 65], "49": [253, 223, 30], "50": [253, 87, 52], "51": [40, 91, 161], "52": [253, 230, 205], "53": [241, 0, 44], "54": [46, 95, 169]}\'']
Traceback (most recent call last):
  File "/usr/local/bin/rubiks-color-resolver.py", line 12, in <module>
    resolve_colors(sys.argv)
  File "/usr/local/lib/python3.7/dist-packages/rubikscolorresolver/solver.py", line 1042, in resolve_colors
    for key, value in scan_data.items():
AttributeError: 'str' object has no attribute 'items'
Error: name 'std_err' is not defined

I seem to have the latest version of rubiks-color-resolver (1.0.0).

dwalton76 commented 1 year ago

Change that to

if True:

For now to get you going

CptDangerous commented 1 year ago

Good morning, BSG (British Standard Grey) day here in southern England.

Some progress in as much as the software takes a photo of each face and prints the result of the .split() function for each face.

Then the following error occurs:

Traceback (most recent call last):
  File "/usr/local/bin/rubiks-color-resolver.py", line 12, in <module>
    resolve_colors(sys.argv)
  File "/usr/local/lib/python3.7/dist-packages/rubikscolorresolver/solver.py", line 1042, in resolve_colors
    for key, value in scan_data.items():
AttributeError: 'str' object has no attribute 'items'
Error: name 'std_err' is not defined

I have what I think is the latest version (1.0.0) of rubiks-color-resolver. Just to be sure I removed all trace of it and re-installed with pip and that was successful.

Here is a sample of what the debug print for a face looks like:

START: Read Face Colors: left
Picture taken
['220, 58, 79', '242, 75, 103', '61, 133, 230', '66, 171, 77', '253, 254, 167', '77, 150, 240', '253, 253, 253', '102, 195, 99', '81, 150, 239']
Vals['220', '58', '79']
Vals['242', '75', '103']
Vals['61', '133', '230']
Vals['66', '171', '77']
Vals['253', '254', '167']
Vals['77', '150', '240']
Vals['253', '253', '253']
Vals['102', '195', '99']
Vals['81', '150', '239']
END: Read Face Colors

Then there is a long string which occurs once at the end of the face reading:

['rubiks-color-resolver.py', '--rgb', '\'{"1": [221, 56, 74], "2": [241, 70, 95], "3": [60, 129, 226], "4": [68, 169, 66], "5": [253, 254, 147], "6": [74, 145, 234], "7": [253, 253, 253], "8": [104, 193, 84], "9": [78, 145, 233], "10": [61, 133, 230], "11": [77, 150, 240], "12": [81, 150, 239], "13": [242, 75, 103], "14": [253, 254, 167], "15": [102, 195, 99], "16": [220, 58, 79], "17": [66, 171, 77], "18": [253, 253, 253], "19": [44, 129, 57], "20": [253, 253, 253], "21": [234, 75, 103], "22": [248, 240, 252], "23": [225, 66, 90], "24": [246, 94, 124], "25": [48, 134, 55], "26": [253, 171, 130], "27": [253, 254, 188], "28": [232, 77, 103], "29": [252, 239, 148], "30": [239, 231, 244], "31": [45, 107, 211], "32": [253, 251, 252], "33": [233, 127, 94], "34": [253, 253, 169], "35": [54, 148, 69], "36": [30, 61, 149], "37": [170, 212, 32], "38": [253, 214, 62], "39": [253, 218, 68], "40": [253, 254, 34], "41": [254, 150, 60], "42": [60, 93, 160], "43": [253, 237, 211], "44": [231, 0, 36], "45": [18, 56, 121], "46": [230, 214, 126], "47": [27, 72, 179], "48": [227, 68, 97], "49": [35, 119, 51], "50": [253, 249, 253], "51": [253, 253, 167], "52": [16, 51, 141], "53": [250, 152, 115], "54": [254, 255, 252]}\'']

I can't see any reference to 'std_err' in the code but either side of line 1042 reads:

    scan_data = eval(rgb)

   for key, value in scan_data.items():
        scan_data[key] = tuple(value)

Just for reference, the left face looked like:

BricKuber_left_face

What I don't understand is that eval(rgb) seems to be returning a string to scan_data, whereas the format of the contents of rgb is that of a dictionary - at least to my untutored eye!

For example (from a different run) where I added a print statement "print('rgb =', rgb)" to get some debug data:

rgb = '{"1": [221, 5, 46], "2": [244, 6, 65], "3": [45, 120, 209], "4": [97, 180, 37], "5": [253, 254, 96], "6": [68, 136, 215], "7": [253, 251, 235], "8": [128, 200, 46], "9": [55, 120, 205], "10": [247, 250, 246], "11": [251, 254, 153], "12": [253, 189, 71], "13": [252, 242, 222], "14": [26, 72, 148], "15": [21, 65, 140], "16": [234, 83, 44], "17": [242, 88, 47], "18": [241, 82, 47], "19": [72, 135, 23], "20": [253, 251, 234], "21": [250, 10, 74], "22": [253, 238, 219], "23": [238, 6, 56], "24": [252, 27, 90], "25": [83, 153, 26], "26": [253, 148, 64], "27": [253, 254, 149], "28": [253, 254, 129], "29": [253, 247, 42], "30": [251, 221, 40], "31": [127, 202, 46], "32": [93, 173, 31], "33": [252, 226, 207], "34": [126, 199, 43], "35": [218, 3, 39], "36": [186, 8, 24], "37": [253, 218, 91], "38": [72, 129, 207], "39": [58, 116, 198], "40": [254, 147, 77], "41": [253, 183, 68], "42": [241, 13, 64], "43": [77, 147, 29], "44": [253, 237, 46], "45": [253, 244, 227], "46": [244, 209, 31], "47": [16, 60, 135], "48": [244, 9, 66], "49": [67, 137, 20], "50": [249, 250, 226], "51": [250, 254, 142], "52": [11, 47, 109], "53": [254, 125, 59], "54": [247, 250, 246]}'

Why doesn't eval(rgb) evaluate to dictionary?

dwalton76 commented 1 year ago

I don't have this robot built to test this but replace the Projects/BricKuber/brickuber_lib.py CameraReadFaceColors method with the following code and give it another try. Post any Tracebacks here and we can go back and forth to get this chunk of code updated.

    def CameraReadFaceColors(self, face):
        debug_print_commands("START: Read Face Colors: " + str(face))
        filename = '/tmp/BricKuber_{}_face.jpg'.format(face)
        subprocess.run(['raspistill', '-w', '300', '-h', '300', '-t', '1', '--imxfx', 'cartoon', '-o', filename])
        subprocess.run(['raspistill', '-w', '300', '-h', '300', '-t', '1', '--sharpness', '-100', '--awb', 'auto', '--imxfx', 'cartoon', '-o', filename])
        subprocess.run(['raspistill', '-w', '300', '-h', '300', '-t', '1', '--imxfx', 'cartoon', '-o', filename])

        debug_print_commands("Picture taken")
        raw_result = subprocess.check_output(['rubiks-cube-tracker.py', '--filename', filename]).decode("utf-8")

        # raw_result.stdout will be a JSON string that looks something like the following.  The key is the 
        # square number and the value is a tuple of RGB ints.
        # {
        #   "1": [234, 126, 92],
        #   "2": [253, 246, 253],
        #   "3": [253, 254, 252],
        #   "4": [232, 123, 89],
        #   "5": [34, 87, 189],
        #   "6": [253, 252, 159],
        #   "7": [230, 118, 87],
        #   "8": [37, 85, 185],
        #   "9": [253, 172, 131]
        # }

        raw_data = json.loads(raw_result.stdout)

        for square, rgb in raw_data.items():
            # BricKuber rgb_values index starts at 0 so subtract 1 from the square value
            self.rgb_values[int(square) - 1] = rgb

        debug_print_commands("END: Read Face Colors")

also you will need to add import json up at the top of the file with the other import statements

CptDangerous commented 1 year ago

Hmmm...

START: Read Face Colors: top
Picture taken
2022-10-10 15:23:32,458            __init__.py     INFO: Analyze /tmp/BricKuber_top_face.jpg
Error: 'str' object has no attribute 'stdout'

So much changed in that last edit. I checked but it seems I cut & pasted it all OK.

dwalton76 commented 1 year ago

On the json.loads line change that to:

raw_data = json.loads(raw_result)

CptDangerous commented 1 year ago

OK, stab in the dark, i removed the .stdout from:

raw_data = json.loads(raw_result)

and the process ran to produce:

['rubiks-color-resolver.py', '--rgb', '\'{"1": [57, 127, 50], "2": [66, 155, 62], "3": [245, 247, 201], "4": [204, 39, 58], "5": [83, 173, 74], "6": [245, 248, 222], "7": [197, 37, 55], "8": [247, 248, 245], "9": [245, 248, 222], "10": [0, 0, 0], "11": [0, 0, 0], "12": [0, 0, 0], "13": [0, 0, 0], "14": [0, 0, 0], "15": [0, 0, 0], "16": [0, 0, 0], "17": [0, 0, 0], "18": [0, 0, 0], "19": [0, 0, 0], "20": [0, 0, 0], "21": [0, 0, 0], "22": [0, 0, 0], "23": [0, 0, 0], "24": [0, 0, 0], "25": [0, 0, 0], "26": [0, 0, 0], "27": [0, 0, 0], "28": [0, 0, 0], "29": [0, 0, 0], "30": [0, 0, 0], "31": [0, 0, 0], "32": [0, 0, 0], "33": [0, 0, 0], "34": [0, 0, 0], "35": [0, 0, 0], "36": [0, 0, 0], "37": [0, 0, 0], "38": [0, 0, 0], "39": [0, 0, 0], "40": [0, 0, 0], "41": [0, 0, 0], "42": [0, 0, 0], "43": [0, 0, 0], "44": [0, 0, 0], "45": [0, 0, 0], "46": [0, 0, 0], "47": [0, 0, 0], "48": [0, 0, 0], "49": [0, 0, 0], "50": [0, 0, 0], "51": [0, 0, 0], "52": [0, 0, 0], "53": [0, 0, 0], "54": [0, 0, 0]}\'']

but the down-stream code still fell over with:

Traceback (most recent call last):
  File "/usr/local/bin/rubiks-color-resolver.py", line 12, in <module>
    resolve_colors(sys.argv)
  File "/usr/local/lib/python3.7/dist-packages/rubikscolorresolver/solver.py", line 1042, in resolve_colors
    for key, value in scan_data.items():
AttributeError: 'str' object has no attribute 'items'
Error: name 'std_err' is not defined

scan_data from this run looks like:

scan_data = {"1": [247, 233, 240], "2": [253, 160, 100], "3": [54, 113, 210], "4": [250, 227, 91], "5": [247, 250, 247], "6": [109, 200, 94], "7": [203, 41, 60], "8": [46, 98, 196], "9": [246, 249, 225], "10": [0, 0, 0], "11": [0, 0, 0], "12": [0, 0, 0], "13": [0, 0, 0], "14": [0, 0, 0], "15": [0, 0, 0], "16": [0, 0, 0], "17": [0, 0, 0], "18": [0, 0, 0], "19": [0, 0, 0], "20": [0, 0, 0], "21": [0, 0, 0], "22": [0, 0, 0], "23": [0, 0, 0], "24": [0, 0, 0], "25": [0, 0, 0], "26": [0, 0, 0], "27": [0, 0, 0], "28": [0, 0, 0], "29": [0, 0, 0], "30": [0, 0, 0], "31": [0, 0, 0], "32": [0, 0, 0], "33": [0, 0, 0], "34": [0, 0, 0], "35": [0, 0, 0], "36": [0, 0, 0], "37": [0, 0, 0], "38": [0, 0, 0], "39": [0, 0, 0], "40": [0, 0, 0], "41": [0, 0, 0], "42": [0, 0, 0], "43": [0, 0, 0], "44": [0, 0, 0], "45": [0, 0, 0], "46": [0, 0, 0], "47": [0, 0, 0], "48": [0, 0, 0], "49": [0, 0, 0], "50": [0, 0, 0], "51": [0, 0, 0], "52": [0, 0, 0], "53": [0, 0, 0], "54": [0, 0, 0]}

which looks a lot like a dictionary to me, but with rubbish entries! Only the 1st face data looks right, then all after is zeros.

CptDangerous commented 1 year ago

OK, real progress!!!

I reverted to the original copy of brickuber_lib.py and changed the following in /usr/local/lib/python3.7/dist-packages/rubikscolorresolver/solver.py

    # scan_data = eval(rgb)
    scan_data = json.loads(eval(rgb))
    print('scan_data =', scan_data)    # my debug print statement

Having added import json at the top of the code.

Process ran to:

['rubiks-color-resolver.py', '--rgb', '\'{"1": [235, 211, 34], "2": [227, 229, 218], "3": [222, 4, 44], "4": [234, 218, 29], "5": [83, 159, 29], "6": [235, 7, 54], "7": [235, 211, 29], "8": [92, 166, 32], "9": [157, 201, 68], "10": [18, 74, 160], "11": [47, 100, 183], "12": [68, 112, 187], "13": [217, 6, 40], "14": [235, 239, 102], "15": [97, 177, 42], "16": [199, 8, 34], "17": [64, 145, 22], "18": [234, 232, 213], "19": [186, 7, 31], "20": [207, 2, 34], "21": [231, 236, 86], "22": [233, 222, 200], "23": [218, 7, 44], "24": [241, 181, 48], "25": [59, 119, 18], "26": [229, 231, 227], "27": [117, 184, 45], "28": [232, 22, 62], "29": [229, 233, 81], "30": [230, 220, 198], "31": [31, 80, 162], "32": [227, 229, 222], "33": [236, 84, 41], "34": [229, 233, 101], "35": [65, 139, 18], "36": [9, 42, 100], "37": [93, 170, 31], "38": [238, 196, 54], "39": [238, 205, 67], "40": [232, 234, 30], "41": [241, 157, 43], "42": [49, 85, 156], "43": [231, 223, 199], "44": [200, 2, 33], "45": [9, 47, 112], "46": [232, 72, 40], "47": [10, 49, 117], "48": [240, 158, 46], "49": [235, 211, 33], "50": [19, 60, 130], "51": [238, 187, 50], "52": [231, 216, 195], "53": [227, 229, 225], "54": [238, 187, 59]}\'']
scan_data = {'1': [235, 211, 34], '2': [227, 229, 218], '3': [222, 4, 44], '4': [234, 218, 29], '5': [83, 159, 29], '6': [235, 7, 54], '7': [235, 211, 29], '8': [92, 166, 32], '9': [157, 201, 68], '10': [18, 74, 160], '11': [47, 100, 183], '12': [68, 112, 187], '13': [217, 6, 40], '14': [235, 239, 102], '15': [97, 177, 42], '16': [199, 8, 34], '17': [64, 145, 22], '18': [234, 232, 213], '19': [186, 7, 31], '20': [207, 2, 34], '21': [231, 236, 86], '22': [233, 222, 200], '23': [218, 7, 44], '24': [241, 181, 48], '25': [59, 119, 18], '26': [229, 231, 227], '27': [117, 184, 45], '28': [232, 22, 62], '29': [229, 233, 81], '30': [230, 220, 198], '31': [31, 80, 162], '32': [227, 229, 222], '33': [236, 84, 41], '34': [229, 233, 101], '35': [65, 139, 18], '36': [9, 42, 100], '37': [93, 170, 31], '38': [238, 196, 54], '39': [238, 205, 67], '40': [232, 234, 30], '41': [241, 157, 43], '42': [49, 85, 156], '43': [231, 223, 199], '44': [200, 2, 33], '45': [9, 47, 112], '46': [232, 72, 40], '47': [10, 49, 117], '48': [240, 158, 46], '49': [235, 211, 33], '50': [19, 60, 130], '51': [238, 187, 50], '52': [231, 216, 195], '53': [227, 229, 225], '54': [238, 187, 59]}
Cube

           Ye Wh Rd
           Ye Gr Rd
           Ye Gr Gr
 Bu Bu Bu  Rd Rd Ye  Rd Ye Wh  Gr OR OR
 Rd Ye Gr  Wh Rd OR  Bu Wh OR  Ye OR Bu
 Rd Gr Wh  Gr Wh Gr  Ye Gr Bu  Wh Rd Bu
           OR Bu OR
           Ye Bu OR
           Wh Wh OR
LRFLUFLUUFLRDRBLUDFFLRFBURUBDBLDBRRBDDDFLUFURUBBLBDRFD
Error: name 'std_err' is not defined

So all the double quotes were converted to single quotes and the string was treated as a dictionary. Whoopee!

The final Error: must be somewhere in the kociemba code.

Very many thanks for all your help. I'll try and leave you in peace. :-)

Cheers, Chris

PS the BSG turned into a lovely, sunny autumn (fall) day.

dwalton76 commented 1 year ago

I see what is happening...replace your file with this and give it another go https://raw.githubusercontent.com/dwalton76/BrickPi3/master/Projects/BricKuber/brickuber_lib.py

dwalton76 commented 1 year ago

ok this part

LRFLUFLUUFLRDRBLUDFFLRFBURUBDBLDBRRBDDDFLUFURUBBLBDRFD
Error: name 'std_err' is not defined

I think you are also running an older copy of rubiks-color-resolver so you need to uninstall/re-install that via

sudo find /usr -name rubikscolorresolver* | xargs rm -rf
sudo find /usr -name rubiks-color-resolver.py | xargs rm -rf
sudo pip install git+https://github.com/dwalton76/rubiks-color-resolver.git
CptDangerous commented 1 year ago

No, I'm using the latest & greatest rubiks-color-resolver as I mentioned recently. However, using the brickuber_lib.py from your BricKuber repository gets me a long way down the line.

Cube

           Bu Gr Rd
           Ye OR Gr
           OR Bu Rd
 OR Rd Ye  Gr Rd Gr  Ye Ye Ye  Bu Rd Ye
 Gr Ye Ye  OR Gr Bu  OR Wh OR  Wh Bu Wh
 Bu Ye Wh  Gr Gr Wh  Rd Rd OR  Bu Bu Wh
           OR OR Gr
           Bu Rd Wh
           Rd Wh Wh

BFDLUFUBDLLLURUDDUFDFUFBFFRUUFBDRDRRUDLFLLBLRBDLRBRBBR

Using kociemba to compute an efficient solve solution.
Error: Error. Probably cubestring is invalid

The whole face scan operation is inordinately sensitive to light source and intensity.

But we're nearly there. Just tweaking of the illumination is required now I believe.

Many, many thanks for all your help and for the software.

Cheers & beers, Chris

dwalton76 commented 1 year ago

For the RGB values you posted about 2 hours ago everything is good image

For the one above where you got the Probably cubestring is invalid, can you send me the RGB json string that was passed to rubiks-color-resolver.py? If you aren't sure what the values were just attach the /tmp/rubiks-color-resolver.html file to the issue here...that is the debug output from the color resolver

CptDangerous commented 1 year ago

Unfortunately I shut the RPi down and all the dumps which were only on a terminal are now lost along with a lot of the contents of /tmp.

I'm off to bed. Let me know if there is anything I can post tomorrow.

CptDangerous commented 1 year ago

Did another quick run before retiring:

['rubiks-color-resolver.py', '--rgb', '{"1": [52, 113, 1], "2": [230, 1, 41], "3": [113, 194, 29], "4": [82, 157, 16], "5": [96, 181, 21], "6": [253, 159, 72], "7": [253, 233, 46], "8": [9, 72, 167], "9": [140, 210, 34], "19": [224, 98, 60], "20": [201, 38, 46], "21": [253, 239, 105], "22": [230, 107, 63], "23": [251, 237, 236], "24": [253, 163, 92], "25": [230, 107, 63], "26": [207, 41, 47], "27": [253, 244, 90], "46": [24, 53, 130], "47": [252, 241, 246], "48": [31, 85, 190], "49": [243, 227, 232], "50": [26, 72, 169], "51": [253, 247, 95], "52": [12, 50, 139], "53": [26, 71, 167], "54": [254, 254, 252], "28": [29, 63, 156], "29": [76, 171, 55], "30": [242, 63, 86], "31": [253, 246, 253], "32": [253, 170, 104], "33": [108, 198, 68], "34": [213, 38, 49], "35": [38, 96, 202], "36": [249, 77, 97], "37": [161, 27, 33], "38": [235, 128, 87], "39": [253, 248, 253], "40": [230, 219, 236], "41": [243, 226, 117], "42": [253, 239, 138], "43": [221, 101, 67], "44": [242, 223, 112], "45": [253, 247, 253], "10": [252, 219, 48], "11": [4, 56, 148], "12": [253, 136, 74], "13": [69, 144, 10], "14": [233, 1, 43], "15": [250, 6, 61], "16": [253, 232, 217], "17": [253, 242, 38], "18": [123, 193, 25]}']
Cube

           Gr OR Gr
           OR Gr Ye
           Ye Bu Ye
 OR Bu Gr  OR Rd OR  Bu Gr Ye  Rd Ye Wh
 Gr Rd Rd  Ye Wh OR  Wh OR Gr  Rd Ye OR
 Wh Gr Wh  OR Rd Ye  Rd Bu Rd  Gr Wh Rd
           Bu Wh Bu
           Wh Bu Ye
           Bu Bu Wh
URURUBBDBDUBFRULDLRLRBFRRLBDFDFDBDDFRDUULLFUFLBFLBRUFL

Using kociemba to compute an efficient solve solution.
Error: Error. Probably cubestring is invalid

The actual faces are:

top: BricKuber_top_face

front: BricKuber_front_face

bottom: BricKuber_bottom_face

right: BricKuber_right_face

back: BricKuber_back_face

left: BricKuber_left_face

Lots of misinterpreted colours especially Rd->Or, Or->Ye, Ye->Wh etc.

Bottom is completely correct but most other faces have misinterpreted colours.

Ah, the other thing you asked for was the rgb data from rubiks-color-resolver.html:

RGB Input
{'1': (52, 113, 1), '2': (230, 1, 41), '3': (113, 194, 29), '4': (82, 157, 16), '5': (96, 181, 21), '6': (253, 159, 72), '7': (253, 233, 46), '8': (9, 72, 167), '9': (140, 210, 34), '19': (224, 98, 60), '20': (201, 38, 46), '21': (253, 239, 105), '22': (230, 107, 63), '23': (251, 237, 236), '24': (253, 163, 92), '25': (230, 107, 63), '26': (207, 41, 47), '27': (253, 244, 90), '46': (24, 53, 130), '47': (252, 241, 246), '48': (31, 85, 190), '49': (243, 227, 232), '50': (26, 72, 169), '51': (253, 247, 95), '52': (12, 50, 139), '53': (26, 71, 167), '54': (254, 254, 252), '28': (29, 63, 156), '29': (76, 171, 55), '30': (242, 63, 86), '31': (253, 246, 253), '32': (253, 170, 104), '33': (108, 198, 68), '34': (213, 38, 49), '35': (38, 96, 202), '36': (249, 77, 97), '37': (161, 27, 33), '38': (235, 128, 87), '39': (253, 248, 253), '40': (230, 219, 236), '41': (243, 226, 117), '42': (253, 239, 138), '43': (221, 101, 67), '44': (242, 223, 112), '45': (253, 247, 253), '10': (252, 219, 48), '11': (4, 56, 148), '12': (253, 136, 74), '13': (69, 144, 10), '14': (233, 1, 43), '15': (250, 6, 61), '16': (253, 232, 217), '17': (253, 242, 38), '18': (123, 193, 25)}

gzipped .html file:

rubiks-color-resolver.html.gz

dwalton76 commented 1 year ago

This is from the html file, these are the initial RGB values image

Look at that "7, 19, 12" corner, 12 and 19 are both orange both in that data and in your pictures above. This tells us the robot is making a mistake in how it rotates the cube around to take pics of each side. Do this for me...hold the cube so that you are looking at the front face as shown in the pic above and turn the cube enough so that I can see the left/front sides at the same time and send me a pic of that (just from your cell phone, not the robot). Same thing for the front/right side.

CptDangerous commented 1 year ago

IMG_0067

I think I see what you mean. That L face is rotated 90 clockwise in the cube view (not the photo).

IMG_0068

...and the R face is 180 out.

Looks like the self.SPIN_DIRECTION = 1 has changed polarity?

dwalton76 commented 1 year ago

This is the section that needs tweaking https://github.com/dwalton76/BrickPi3/blob/master/Projects/BricKuber/brickuber_lib.py#L330-L342

        self.CameraReadFaceColors("top")
        self.flip(True)
        self.CameraReadFaceColors("front")
        self.flip(True)
        self.CameraReadFaceColors("bottom")
        self.spin(90)
        self.flip(True)
        self.CameraReadFaceColors("right")
        self.spin(-90)
        self.flip(True)
        self.CameraReadFaceColors("back")
        self.flip(True)
        self.CameraReadFaceColors("left")
        self.CCO = [5, 1, 0]

To test your SPIN_POLARITY theory change the 90 above to -90 and vice versa. Then rescan and look at the pictures and see if they look right.

If that doesn't work you'll need experiment with adding/removing self.spin(90) in various places above so that the cube is rotated correctly when we take the picture. Once that is ironed out we need to sanity check that self.CCO = [5, 1, 0] line...that is the state of which side of the cube is facing which direction but I don't entirely follow the logic yet.

CptDangerous commented 1 year ago

OK, I only changed the self.spin(+/-90) lines, ran the program and it said everything was OK and tried to apply the solution. But the cube was a jumble. So I reverted the changes and just changed the spin polarity line and got:

Error: Error. Probably cubestring is invalid

Just checking the faces with the cube layout diagram...

CptDangerous commented 1 year ago

Hmmm... can't match any face with the cube layout!

My brain is beginning to hurt!

dwalton76 commented 1 year ago

OK, I only changed the self.spin(+/-90) lines, ran the program and it said everything was OK lets focus on that first...don't worry about if it can solve it just yet. After it takes the pictures pull the cube out of the robot and

Once we can answer yes to both of those questions then we just need to figure out what the self.CCO = ... should be and then it should be able to solve it.

CptDangerous commented 1 year ago

Reference point: self.spin(+/-90) reversed from issued code:

        # self.spin(90)
        self.spin(-90)
        self.flip(True)
        self.CameraReadFaceColors("right")
        # self.spin(-90)
        self.spin(90)

Images are not rotated correctly:

L cube face is rotated 90 counterclockwise reference cube layout.

R cube face is rotated 180 clockwise reference cube layout.

However all colours have been correctly interpreted.

CptDangerous commented 1 year ago

rubiks-color-resolver.html.gz