Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import os
- import cv2
- import time
- import threading
- import numpy as np
- from flask import Flask, Response, request
- os.environ["OPENCV_LOG_LEVEL"] = "FATAL"
- app = Flask(__name__)
- cap = None
- TERM_WIDTH = 51
- TERM_HEIGHT = 19
- PIXEL_WIDTH = TERM_WIDTH * 6
- PIXEL_HEIGHT = TERM_HEIGHT * 9
- latest_frame = None
- frame_lock = threading.Lock()
- capture_running = False
- CC_16_COLORS = np.array([
- [240, 240, 240],
- [242, 178, 51],
- [229, 127, 216],
- [153, 178, 242],
- [222, 222, 108],
- [127, 204, 25],
- [242, 178, 204],
- [76, 76, 76],
- [153, 153, 153],
- [76, 153, 178],
- [127, 63, 178],
- [51, 51, 178],
- [102, 76, 51],
- [102, 127, 51],
- [153, 51, 51],
- [25, 25, 25]
- ], dtype=np.float32)
- BAYER_4X4 = np.array([
- [0, 8, 2, 10],
- [12, 4, 14, 6],
- [3, 11, 1, 9],
- [15, 7, 13, 5]
- ], dtype=np.float32) / 16.0 - 0.5
- def get_dither_matrix(h, w):
- tiled = np.tile(BAYER_4X4, (int(np.ceil(h / 4)), int(np.ceil(w / 4))))
- return tiled[:h, :w, np.newaxis]
- def get_available_cameras():
- available_cameras = []
- backend = cv2.CAP_DSHOW if os.name == 'nt' else cv2.CAP_ANY
- for i in range(2):
- temp_cap = cv2.VideoCapture(i, backend)
- if temp_cap.isOpened():
- success, _ = temp_cap.read()
- if success:
- available_cameras.append(i)
- temp_cap.release()
- return available_cameras
- def resize_with_aspect_ratio(frame, target_w, target_h):
- src_h, src_w = frame.shape[:2]
- scale = min(target_w / src_w, target_h / src_h)
- new_w = max(1, round(src_w * scale))
- new_h = max(1, round(src_h * scale))
- resized = cv2.resize(frame, (new_w, new_h), interpolation=cv2.INTER_AREA)
- canvas = np.zeros((target_h, target_w, 3), dtype=np.uint8)
- x_off = (target_w - new_w) // 2
- y_off = (target_h - new_h) // 2
- canvas[y_off:y_off + new_h, x_off:x_off + new_w] = resized
- return canvas
- def capture_loop():
- global latest_frame, capture_running
- dither = get_dither_matrix(PIXEL_HEIGHT, PIXEL_WIDTH) * 24
- while capture_running and cap and cap.isOpened():
- success, frame = cap.read()
- if not success:
- time.sleep(0.01)
- continue
- resized = resize_with_aspect_ratio(frame, PIXEL_WIDTH, PIXEL_HEIGHT)
- dithered = np.clip(resized.astype(np.float32) + dither, 0, 255).astype(np.uint8)
- with frame_lock:
- latest_frame = dithered
- time.sleep(0.02)
- def generate_video_stream(mode):
- cube_size = 5
- while capture_running:
- with frame_lock:
- frame = None if latest_frame is None else latest_frame.copy()
- if frame is None:
- time.sleep(0.01)
- continue
- pixels = frame.reshape((-1, 3)).astype(np.float32)
- if mode == 1:
- b_val = pixels[:, 0]
- g_val = pixels[:, 1]
- r_val = pixels[:, 2]
- r_idx = (r_val * (cube_size - 1)) // 255
- g_idx = (g_val * (cube_size - 1)) // 255
- b_idx = (b_val * (cube_size - 1)) // 255
- color_indices = 16 + r_idx * (cube_size * cube_size) + g_idx * cube_size + b_idx
- else:
- distances = np.sqrt(np.sum((pixels[:, np.newaxis, :] - CC_16_COLORS[np.newaxis, :, :]) ** 2, axis=2))
- color_indices = np.argmin(distances, axis=1)
- yield color_indices.astype(np.uint8).tobytes()
- time.sleep(0.03)
- @app.route('/stream')
- def stream():
- mode = int(request.args.get('mode', 1))
- return Response(generate_video_stream(mode), mimetype='application/octet-stream')
- if __name__ == '__main__':
- devices = get_available_cameras()
- if not devices:
- print("Error: No active cameras found!")
- exit(1)
- selected_index = devices[0]
- cap = cv2.VideoCapture(selected_index, cv2.CAP_DSHOW if os.name == 'nt' else cv2.CAP_ANY)
- cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)
- cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc(*'MJPG'))
- if not cap.isOpened():
- print(f"Error: Could not open device {selected_index}.")
- exit(1)
- capture_running = True
- capture_thread = threading.Thread(target=capture_loop, daemon=True)
- capture_thread.start()
- print("Flask server running on http://0.0.0.0:5000/stream ...")
- try:
- app.run(host='0.0.0.0', port=5000, threaded=True)
- finally:
- capture_running = False
- capture_thread.join(timeout=2)
- if cap:
- cap.release()
Advertisement