Неделя 13 - Оптимизация и развертывание решений компьютерного зрения
1. Оптимизация производительности
1.1. Векторизация операций с NumPy
python
Copy
# Неоптимизированный вариант (поэлементная обработка)
def slow_grayscale(img):
h, w = img.shape[:2]
gray = np.zeros((h, w), dtype=np.uint8)
for i in range(h):
for j in range(w):
gray[i,j] = 0.299*img[i,j,0] + 0.587*img[i,j,1] + 0.114*img[i,j,2]
return gray
# Оптимизированный вариант (векторизация)
def fast_grayscale(img):
return np.uint8(0.299*img[:,:,0] + 0.587*img[:,:,1] + 0.114*img[:,:,2])
1.2. Использование UMat (GPU-ускорение)
python
Copy
# Обычная операция на CPU
img = cv2.imread('large_image.jpg')
blur_cpu = cv2.GaussianBlur(img, (25,25), 0)
# Операция с GPU-ускорением (если доступно)
img_umat = cv2.UMat(img)
blur_gpu = cv2.GaussianBlur(img_umat, (25,25), 0)
blur_result = blur_gpu.get() # Возвращаем на CPU
1.3. Многопоточная обработка
python
Copy
from concurrent.futures import ThreadPoolExecutor
import multiprocessing
def process_frame(frame):
# Операции обработки кадра
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 100, 200)
return edges
def parallel_video_processing(video_path, num_workers=None):
if num_workers is None:
num_workers = multiprocessing.cpu_count()
cap = cv2.VideoCapture(video_path)
frames = []
with ThreadPoolExecutor(max_workers=num_workers) as executor:
while True:
ret, frame = cap.read()
if not ret:
break
frames.append(executor.submit(process_frame, frame))
# Получение результатов
processed_frames = [f.result() for f in frames]
cap.release()
return processed_frames
2. Уменьшение вычислительной сложности
2.1. Масштабирование изображений
python
Copy
def pyramid_processing(img, scale=0.5, min_size=100):
# Создание пирамиды изображений
pyramid = [img]
while True:
w = int(pyramid[-1].shape[1] * scale)
h = int(pyramid[-1].shape[0] * scale)
if w < min_size or h < min_size:
break
resized = cv2.resize(pyramid[-1], (w,h))
pyramid.append(resized)
return pyramid
# Обработка на уменьшенном изображении с последующим уточнением
2.2. ROI (Region of Interest) обработка
python
Copy
def selective_processing(img, detection_interval=10):
processed = img.copy()
h, w = img.shape[:2]
# Обрабатываем только каждую 10-ю строку для детекции
for y in range(0, h, detection_interval):
roi = img[y:y+1, 0:w] # Полоса высотой 1 пиксель
# Анализ ROI и обработка при необходимости
if needs_processing(roi):
full_roi = img[max(0,y-50):min(h,y+50), 0:w]
processed_roi = full_processing(full_roi)
processed[max(0,y-50):min(h,y+50), 0:w] = processed_roi
return processed
3. Развертывание решений
3.1. Создание REST API с Flask
python
Copy
from flask import Flask, request, jsonify
import cv2
import numpy as np
import io
app = Flask(__name__)
@app.route('/process_image', methods=['POST'])
def process_image():
# Получение изображения из запроса
file = request.files['image']
img_bytes = file.read()
img = cv2.imdecode(np.frombuffer(img_bytes, np.uint8), cv2.IMREAD_COLOR)
# Обработка изображения
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 100, 200)
# Возврат результата
_, img_encoded = cv2.imencode('.jpg', edges)
return jsonify({'result': img_encoded.tobytes().hex()})
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
3.2. Упаковка в Docker-контейнер
dockerfile
Copy
FROM python:3.8-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app.py .
CMD ["gunicorn", "--bind", "0.0.0.0:5000", "app:app"]
3.3. Использование ONNX для кроссплатформенного развертывания
python
Copy
# Конвертация модели в ONNX формат
import torch
model = torch.hub.load('ultralytics/yolov5', 'yolov5s', pretrained=True)
dummy_input = torch.randn(1, 3, 640, 640)
torch.onnx.export(model, dummy_input, "yolov5s.onnx")
# Загрузка и использование ONNX модели в OpenCV
net = cv2.dnn.readNetFromONNX("yolov5s.onnx")
blob = cv2.dnn.blobFromImage(img, 1/255.0, (640,640), swapRB=True)
net.setInput(blob)
outputs = net.forward()
4. Оптимизация для мобильных устройств
4.1. Квантование моделей
python
Copy
import tensorflow as tf
# Загрузка модели
model = tf.keras.models.load_model('my_model.h5')
# Квантование
converter = tf.lite.TFLiteConverter.from_keras_model(model)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
quantized_model = converter.convert()
# Сохранение
with open('model_quant.tflite', 'wb') as f:
f.write(quantized_model)
4.2. Использование OpenCV для мобильных приложений
java
Copy
// Пример для Android (Java)
Mat img = new Mat();
Utils.bitmapToMat(bitmap, img);
Imgproc.cvtColor(img, img, Imgproc.COLOR_RGB2GRAY);
Imgproc.Canny(img, img, 50, 150);
Utils.matToBitmap(img, bitmap);
imageView.setImageBitmap(bitmap);
5. Практическое задание
1. Сравните производительность обычной и векторизованной реализации операции
2. Реализуйте многопоточную обработку видеофайла
3. Создайте Flask API для обработки изображений
4. Упакуйте решение в Docker-контейнер
5. (Дополнительно) Сконвертируйте модель в ONNX и запустите на разных платформах
6. Итоги
Векторизация и GPU-ускорение значительно повышают производительность
Многопоточность позволяет эффективно обрабатывать видео
REST API и Docker упрощают развертывание решений
ONNX и квантование помогают в кроссплатформенном развертывании
Оптимизация особенно важна для мобильных приложений
Следующая тема: Финальный проект - разработка комплексной системы компьютерного зрения