travail d'un we (j'en ai big marre)
1
.cache
@@ -1 +0,0 @@
|
|||||||
{"access_token": "BQDeVV_yylewo72n9ZtSMTn1WNhJKSbUBDKv18Cl-QY7dphidwC9jDuGuZWKaIWZv-fVIG1uuP1XvJFKwcj3GOxgRxYJbaWOLtogCHkAxC-iOaZe6uphn-vCy5rbX6Xlx9XVUG-jHNu0jaCf1-ueTRUQuyF0Btu4_aAcIktTnYyofSUJuk_Mdi1J6V3hmARkCl34Rv-4hgfXcIqQ_rpdCFHGheEU1rSL5oME", "token_type": "Bearer", "expires_in": 3600, "scope": "user-modify-playback-state user-read-playback-state", "expires_at": 1757966041, "refresh_token": "AQAxD3wm_8aDlK9w2ZsibKsrPY0SxUJb2UaqiT2ygxK-pEq2ojxPzgLa6DNt9EpP3mjFDCLmGO5glj5fSpR3ZnqEa26belG4EQv5FOeee38ix31o2xuxPbDsY44KR5Uj1KE"}
|
|
||||||
10
final-loop/Dockerfile
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
FROM python:3.11-slim
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY requirements.txt ./
|
||||||
|
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
COPY src/ .
|
||||||
|
|
||||||
1
final-loop/client-cache/credentials.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"username":"mathias-120","auth_type":1,"auth_data":"QWdDZF9iOVZDTUltQ0Noc0lnSFdfNU5QOXBMdFdiQllFclJ3dHM3ZVRaY1lzUEpKd1Jwc1pOc3FzdjFwYnRYZ2ZRSXE2Q1ZiWTBjdzRDTUYzdkJMekdqOVliRTh1UldlZlJOdF94eEgydzJUWmhtT0RlX295ODdrTzZDYXFuMW5SVEQ4TV95S2R0aEJLTDZldkxPeDlva0wtcHJNY0p6Q3VzQl9YOGFhVHNYaw=="}
|
||||||
1
final-loop/client-cache/volume
Normal file
@@ -0,0 +1 @@
|
|||||||
|
65535
|
||||||
34
final-loop/compose.yml
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
services:
|
||||||
|
librespot:
|
||||||
|
container_name: spotvinyl-client
|
||||||
|
image: giof71/librespot:latest
|
||||||
|
network_mode: host
|
||||||
|
devices:
|
||||||
|
- /dev/snd:/dev/snd
|
||||||
|
environment:
|
||||||
|
- DEVICE=hw:x20,0
|
||||||
|
- BACKEND=alsa
|
||||||
|
- BITRATE=320
|
||||||
|
- INITIAL_VOLUME=100
|
||||||
|
- DEVICE_NAME=spotvinyl
|
||||||
|
- ENABLE_OAUTH=headless # Enables OAuth headless mode
|
||||||
|
- ENABLE_SYSTEM_CACHE=Y # Cache token for persistent login
|
||||||
|
volumes:
|
||||||
|
- ./client-cache:/data/system-cache
|
||||||
|
stdin_open: true
|
||||||
|
tty: true
|
||||||
|
|
||||||
|
spotvinyl:
|
||||||
|
build: .
|
||||||
|
container_name: spotvinyl
|
||||||
|
devices:
|
||||||
|
- /dev/video2
|
||||||
|
volumes:
|
||||||
|
- ./src:/app
|
||||||
|
# - ./spotvinyl-cache
|
||||||
|
working_dir: /app
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
command: python3 decode_barcode.py
|
||||||
|
ports:
|
||||||
|
- "5000:5000"
|
||||||
32
final-loop/requirements.txt
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
certifi==2025.11.12
|
||||||
|
chardet==5.2.0
|
||||||
|
charset-normalizer==3.4.4
|
||||||
|
contourpy==1.3.3
|
||||||
|
crccheck==1.3.1
|
||||||
|
cycler==0.12.1
|
||||||
|
decorator==5.2.1
|
||||||
|
fonttools==4.60.1
|
||||||
|
idna==3.11
|
||||||
|
ImageIO==2.37.2
|
||||||
|
joblib==1.5.2
|
||||||
|
kiwisolver==1.4.9
|
||||||
|
lazy_loader==0.4
|
||||||
|
matplotlib==3.10.7
|
||||||
|
networkx==3.5
|
||||||
|
numpy==2.2.6
|
||||||
|
opencv-python==4.12.0.88
|
||||||
|
packaging==25.0
|
||||||
|
pillow==12.0.0
|
||||||
|
pyparsing==3.2.5
|
||||||
|
python-dateutil==2.9.0.post0
|
||||||
|
PyWavelets==1.9.0
|
||||||
|
redis==7.1.0
|
||||||
|
requests==2.32.5
|
||||||
|
scikit-image==0.25.2
|
||||||
|
scikit-learn==1.7.2
|
||||||
|
scipy==1.16.3
|
||||||
|
six==1.17.0
|
||||||
|
spotipy==2.25.1
|
||||||
|
threadpoolctl==3.6.0
|
||||||
|
tifffile==2025.10.16
|
||||||
|
urllib3==2.5.0
|
||||||
@@ -1 +0,0 @@
|
|||||||
{"access_token": "BQAHRFXWQMMKWNbUO3sfhk92iUGi5VJNZmB2lTjRim-g2AIe88mgDvyc1NywjCVBTeZK-b3PkXzGDANJDDOouitEt5P8z0jpVuPrpalwAg0PzEwtKBXr8PHvacajO9B3s7Wy0s7G3CFlfGfbOfmXtW_vF8G2_ooGnlFp_oM8RcOyBl7D5Okf6kr07CWIJty4mNeTf1Ifd212u1tBnbU64lckqlQ0f0W105mt", "token_type": "Bearer", "expires_in": 3600, "refresh_token": "AQCSe9ARCDB-Q6gzna_KKAlcEuNOx2IC9BSVXS5GZxNDi4AjJdA4Kn3hp1YPfiPfogd2rz-5zLbyjUxiRj9oTd-q5EItEPZHIVt-eMf7gCGHfj6h-hLpRrnhgMZjzRAS7CY", "scope": "user-modify-playback-state user-read-playback-state", "expires_at": 1757966002}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
certifi>=2023.5.7
|
|
||||||
chardet>=5.1.0
|
|
||||||
crccheck>=1.0
|
|
||||||
cycler>=0.11.0
|
|
||||||
decorator>=5.1.1
|
|
||||||
idna>=3.5
|
|
||||||
imageio>=2.31.1
|
|
||||||
kiwisolver>=1.4.4
|
|
||||||
matplotlib>=3.7.1
|
|
||||||
networkx>=3.1
|
|
||||||
numpy>=1.24.2
|
|
||||||
Pillow>=10.0.0
|
|
||||||
pyparsing>=3.0.9
|
|
||||||
python-dateutil>=2.8.2
|
|
||||||
PyWavelets>=1.4.1
|
|
||||||
requests>=2.31.0
|
|
||||||
scikit-image>=0.25.2
|
|
||||||
scipy>=1.11.1
|
|
||||||
six>=1.16.0
|
|
||||||
tifffile>=2023.7.23
|
|
||||||
urllib3>=2.0.4
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
import argparse
|
|
||||||
import pprint
|
|
||||||
from get_heights import get_heights
|
|
||||||
from encode_decode import spotify_bar_decode
|
|
||||||
from get_uri import get_uri, get_info
|
|
||||||
import cv2
|
|
||||||
|
|
||||||
|
|
||||||
def process_frame(frame, token):
|
|
||||||
heights = get_heights(frame)
|
|
||||||
print(len(heights)) # assumes get_heights can take image array
|
|
||||||
if len(heights) != 23:
|
|
||||||
return None # skip bad frames
|
|
||||||
else:
|
|
||||||
print("ON TROUVE UN CODE")
|
|
||||||
|
|
||||||
heights = heights[1:11] + heights[12:-1]
|
|
||||||
decoded = spotify_bar_decode(heights)
|
|
||||||
uri = get_uri(decoded, token)
|
|
||||||
summary, full_response = get_info(uri["target"], token)
|
|
||||||
return summary
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
parser = argparse.ArgumentParser()
|
|
||||||
parser.add_argument("--token", required=True)
|
|
||||||
args = parser.parse_args()
|
|
||||||
token = args.token
|
|
||||||
|
|
||||||
cap = cv2.VideoCapture(0) # 0 for default webcam
|
|
||||||
|
|
||||||
while True:
|
|
||||||
ret, frame = cap.read()
|
|
||||||
if not ret:
|
|
||||||
break
|
|
||||||
|
|
||||||
# Définir les dimensions et la marge du cadre
|
|
||||||
height, width, _ = frame.shape
|
|
||||||
margin = 100 # ajustez la taille du cadre ici
|
|
||||||
frame = frame[margin:height - margin, margin:width - margin]
|
|
||||||
|
|
||||||
try:
|
|
||||||
summary = process_frame(frame, token)
|
|
||||||
except Exception:
|
|
||||||
continue
|
|
||||||
|
|
||||||
if summary:
|
|
||||||
print("Summary:")
|
|
||||||
pprint.pprint(summary)
|
|
||||||
|
|
||||||
cv2.imshow("Live Barcode", frame)
|
|
||||||
|
|
||||||
if cv2.waitKey(1) & 0xFF == ord('q'):
|
|
||||||
break
|
|
||||||
|
|
||||||
cap.release()
|
|
||||||
cv2.destroyAllWindows()
|
|
||||||
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 15 KiB |
86
final-loop/src/decode_barcode.py
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
import argparse
|
||||||
|
import pprint
|
||||||
|
from get_heights import get_heights
|
||||||
|
from encode_decode import spotify_bar_decode
|
||||||
|
from get_uri import get_uri, get_info
|
||||||
|
import cv2
|
||||||
|
from start_song import start_song
|
||||||
|
import os
|
||||||
|
from flask import Flask, Response
|
||||||
|
import threading
|
||||||
|
import time
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
os.environ["QT_QPA_PLATFORM"] = "xcb"
|
||||||
|
def process_frame(frame, token):
|
||||||
|
|
||||||
|
heights,preprocess = get_heights(frame)
|
||||||
|
cv2.imshow("frame", preprocess)
|
||||||
|
if len(heights)!=23:
|
||||||
|
return None # skip bad frames
|
||||||
|
else:
|
||||||
|
print("ON TROUVE UN CODE")
|
||||||
|
|
||||||
|
|
||||||
|
heights = heights[1:11] + heights[12:-1]
|
||||||
|
decoded = spotify_bar_decode(heights)
|
||||||
|
uri = get_uri(decoded, token)
|
||||||
|
summary, full_response = get_info(uri["target"], token)
|
||||||
|
print(f"SONG FOUND : {summary["name"]}")
|
||||||
|
if uri:
|
||||||
|
start_song(uri['target'],os.getenv('DEVICE_ID'))
|
||||||
|
return summary
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cap = cv2.VideoCapture('/dev/video0')
|
||||||
|
|
||||||
|
|
||||||
|
token = os.getenv('ACCESS_TOKEN')
|
||||||
|
if not token:
|
||||||
|
token = "BQCph85n2Cr-h8jKWhsdsdhywaX3h_bn4pJ_-jdque2u_gn9bI-OdthIowGSU6r058QozL0eJfzy_ClWezXYKrQO2npuyfWVphxSQrKqhBWkGr5bK0UrIfsKKAdJvoNrXD9Db-ObgP5D3-rMpF0Xq3RXwMpTal9NpzTJcHZs_PBjbNClJVy24Jk5WfGbKZPkMs_Hon5TjABx4QzxzE2vxjd4X4EyPlyPuKiIVp-f7yTSJbbRLqt-_O_VJ9mnQ1RgGK16afY7p3JZH_B6-VSCrFuhK_m9yhSieiWoqEeopFEX47Nc4-tuqe8CXcYGiRLZBIcc4w64ly36ZIftxRN7ehcJb2gcV26ZqMS1lg1Yxp0OD4ShJJsinA69X535_w"
|
||||||
|
print(token)
|
||||||
|
|
||||||
|
|
||||||
|
if not cap.isOpened():
|
||||||
|
print("Error: Could not open camera.")
|
||||||
|
exit(1)
|
||||||
|
else:
|
||||||
|
print("Camera is working and ready to capture frames.")
|
||||||
|
|
||||||
|
while True:
|
||||||
|
ret, frame = cap.read()
|
||||||
|
if not ret:
|
||||||
|
break
|
||||||
|
# Crop same as streaming for consistency
|
||||||
|
height, width, _ = frame.shape
|
||||||
|
margin = 100
|
||||||
|
frame = frame[margin:height - margin, margin:width - margin]
|
||||||
|
|
||||||
|
try:
|
||||||
|
|
||||||
|
|
||||||
|
summary = process_frame(frame, token)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
print("")
|
||||||
|
continue
|
||||||
|
# cv2.imshow("preframe", frame)
|
||||||
|
|
||||||
|
if cv2.waitKey(1) & 0xFF == ord('q'):
|
||||||
|
break
|
||||||
|
|
||||||
|
cap.release()
|
||||||
|
cv2.destroyAllWindows()
|
||||||
@@ -8,24 +8,46 @@ from skimage.color import rgb2gray
|
|||||||
import matplotlib.patches as patches
|
import matplotlib.patches as patches
|
||||||
from sklearn.cluster import KMeans
|
from sklearn.cluster import KMeans
|
||||||
import warnings
|
import warnings
|
||||||
|
from skimage.morphology import remove_small_objects
|
||||||
|
from skimage.transform import resize
|
||||||
|
from skimage import exposure
|
||||||
|
from skimage.morphology import erosion, square
|
||||||
|
import cv2
|
||||||
|
from skimage.filters import threshold_local
|
||||||
|
from scipy import ndimage as ndi
|
||||||
|
from skimage.segmentation import watershed
|
||||||
|
from skimage.morphology import opening, rectangle
|
||||||
|
from scipy.ndimage import gaussian_filter
|
||||||
|
|
||||||
warnings.filterwarnings("ignore", category=FutureWarning, message=".*square.*deprecated.*")
|
warnings.filterwarnings("ignore", category=FutureWarning, message=".*square.*deprecated.*")
|
||||||
|
|
||||||
|
#### keep this. If does not work, remove black and reaply the logic only to not-black part of the picture
|
||||||
def get_heights(image):
|
def get_heights(image):
|
||||||
# image = io.imread(filename)
|
# image = io.imread(filename)
|
||||||
|
|
||||||
|
|
||||||
im = rgb2gray(image)
|
im = rgb2gray(image)
|
||||||
binary_im = im > threshold_otsu(im)
|
|
||||||
smooth_im = gaussian(binary_im.astype(float), sigma=1)
|
# Filtrage gaussien léger pour diminuer bruit
|
||||||
morph_im = closing(smooth_im > 0.5, square(3))
|
im_blur = gaussian_filter(im, sigma=1)
|
||||||
labeled = label(morph_im)
|
|
||||||
|
# Calcul du seuil local avec block_size impair, ajuster offset si besoin
|
||||||
|
th = threshold_local(im_blur, block_size=71, offset=-0.09)
|
||||||
|
|
||||||
|
binary_im = im_blur > th
|
||||||
|
|
||||||
|
separated = binary_im
|
||||||
|
labeled = label(separated)
|
||||||
|
|
||||||
bar_dims = [r.bbox for r in regionprops(labeled)]
|
bar_dims = [r.bbox for r in regionprops(labeled)]
|
||||||
bar_dims.sort(key=lambda x: x[1]) # left to right
|
bar_dims.sort(key=lambda x: x[1]) # left to right
|
||||||
|
|
||||||
bars = bar_dims[1:] # skip logo
|
bars = bar_dims#[1:] # skip logo
|
||||||
bar_heights_raw = []
|
bar_heights_raw = []
|
||||||
if(len(bars)!=23):
|
if(len(bars)!=23):
|
||||||
return [0]
|
print(len(bars))
|
||||||
|
return [0], (separated.astype("uint8") * 255) # convert to 0/255 uint8
|
||||||
|
|
||||||
for bar in bars:
|
for bar in bars:
|
||||||
top, left, bottom, right = bar
|
top, left, bottom, right = bar
|
||||||
effective_height = bottom - top # use bounding box height directly
|
effective_height = bottom - top # use bounding box height directly
|
||||||
@@ -44,5 +66,5 @@ def get_heights(image):
|
|||||||
closest_cluster = np.argmin(diffs)
|
closest_cluster = np.argmin(diffs)
|
||||||
predicted_levels.append(int(closest_cluster))
|
predicted_levels.append(int(closest_cluster))
|
||||||
|
|
||||||
|
print(predicted_levels)
|
||||||
return predicted_levels
|
return predicted_levels, (separated.astype("uint8") * 255)
|
||||||
@@ -9,7 +9,7 @@ REDIRECT_URI = 'https://vinyly.couraud.xyz'
|
|||||||
SCOPE = 'user-modify-playback-state user-read-playback-state'
|
SCOPE = 'user-modify-playback-state user-read-playback-state'
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def start_song(URI="spotify:track:0RoA7ObU6phWpqhlC9zH4Z",device_id="a499b8f3684d8098ffb5f9ff11392ebdd61fc6d1"):
|
||||||
auth_manager = SpotifyOAuth(client_id=CLIENT_ID,
|
auth_manager = SpotifyOAuth(client_id=CLIENT_ID,
|
||||||
client_secret=CLIENT_SECRET,
|
client_secret=CLIENT_SECRET,
|
||||||
redirect_uri=REDIRECT_URI,
|
redirect_uri=REDIRECT_URI,
|
||||||
@@ -26,28 +26,18 @@ def main():
|
|||||||
|
|
||||||
sp = spotipy.Spotify(auth_manager=auth_manager)
|
sp = spotipy.Spotify(auth_manager=auth_manager)
|
||||||
|
|
||||||
if len(sys.argv) < 2:
|
|
||||||
print('Usage: python play_spotify.py "song name"')
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
song_name = ' '.join(sys.argv[1:])
|
|
||||||
|
|
||||||
results = sp.search(q=song_name, type='track', limit=1)
|
|
||||||
if not results['tracks']['items']:
|
|
||||||
print(f'No track found for: {song_name}')
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
track_uri = results['tracks']['items'][0]['uri']
|
|
||||||
|
|
||||||
devices = sp.devices()
|
devices = sp.devices()
|
||||||
if not devices['devices']:
|
if not devices['devices']:
|
||||||
print('No active Spotify devices found. Please start playback on a device.')
|
print('No active Spotify devices found. Please start playback on a device.')
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
active_device_id = devices['devices'][0]['id']
|
current = sp.current_user_playing_track()
|
||||||
|
if current and current.get("item"):
|
||||||
|
current_uri = current["item"]["uri"]
|
||||||
|
|
||||||
sp.start_playback(device_id=active_device_id, uris=[track_uri])
|
if current_uri != URI:
|
||||||
print(f'Playing "{song_name}" on device ID: {active_device_id}')
|
sp.start_playback(device_id=device_id, uris=[URI])
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
start_song(URI,device_id)
|
||||||
1
old/.cache
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"access_token": "BQBR3Dnu7QMSOnq8G_8lOiz858WKJmMxiCgskqjp3QDu17EcQWx3Y8ALVQGSXzUcTgkJb-z5oHjJxEQJNfz8tSYREfJGGMKQfoCo0P2tCUbnB0wdGm7iSmWOlYuvrnDTVleJ9nJBGG6vVGc2ZEIl43T54_TmKbkPzampV8FuuGIATUvzbjRO6uEHqzc3ImuBELCZJjj0n8-h4zImXifkJP6pssEY76_GWgKo_HVx", "token_type": "Bearer", "expires_in": 3600, "scope": "user-modify-playback-state user-read-playback-state", "expires_at": 1763737778, "refresh_token": "AQAxD3wm_8aDlK9w2ZsibKsrPY0SxUJb2UaqiT2ygxK-pEq2ojxPzgLa6DNt9EpP3mjFDCLmGO5glj5fSpR3ZnqEa26belG4EQv5FOeee38ix31o2xuxPbDsY44KR5Uj1KE"}
|
||||||
|
Before Width: | Height: | Size: 240 KiB After Width: | Height: | Size: 240 KiB |
|
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 79 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 188 KiB After Width: | Height: | Size: 188 KiB |
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 83 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 129 KiB After Width: | Height: | Size: 129 KiB |
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 71 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 8.6 KiB |
|
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 74 KiB |
|
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 55 KiB |
|
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 9.5 KiB After Width: | Height: | Size: 9.5 KiB |
|
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 83 KiB |
|
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 3.1 MiB After Width: | Height: | Size: 3.1 MiB |
|
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 109 KiB After Width: | Height: | Size: 109 KiB |
|
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 77 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
@@ -21,12 +21,12 @@ def get_heights(filename: str):
|
|||||||
|
|
||||||
bars = bar_dims[1:] # skip logo
|
bars = bar_dims[1:] # skip logo
|
||||||
bar_heights_raw = []
|
bar_heights_raw = []
|
||||||
|
print(len(bars))
|
||||||
for bar in bars:
|
for bar in bars:
|
||||||
top, left, bottom, right = bar
|
top, left, bottom, right = bar
|
||||||
effective_height = bottom - top # use bounding box height directly
|
effective_height = bottom - top # use bounding box height directly
|
||||||
bar_heights_raw.append(effective_height)
|
bar_heights_raw.append(effective_height)
|
||||||
print(len(bars))
|
|
||||||
# Cluster measured heights to 8 clusters representing discrete bar levels
|
# Cluster measured heights to 8 clusters representing discrete bar levels
|
||||||
bar_heights_raw_np = np.array(bar_heights_raw).reshape(-1, 1)
|
bar_heights_raw_np = np.array(bar_heights_raw).reshape(-1, 1)
|
||||||
|
|
||||||
@@ -38,8 +38,8 @@ def get_heights(filename: str):
|
|||||||
for h in bar_heights_raw:
|
for h in bar_heights_raw:
|
||||||
diffs = np.abs(cluster_centers - h)
|
diffs = np.abs(cluster_centers - h)
|
||||||
closest_cluster = np.argmin(diffs)
|
closest_cluster = np.argmin(diffs)
|
||||||
predicted_levels.append(closest_cluster)
|
predicted_levels.append(int(closest_cluster))
|
||||||
|
|
||||||
|
|
||||||
print(len(predicted_levels))
|
print((predicted_levels))
|
||||||
return predicted_levels
|
return predicted_levels
|
||||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 8.6 KiB |
|
Before Width: | Height: | Size: 90 KiB After Width: | Height: | Size: 90 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |