Script Color Cam
unknown
python
9 months ago
17 kB
10
Indexable
# coding=utf-8
import mvsdk
import numpy as np
import cv2
import os
import time
import ctypes
import json
def main():
# Перечисление доступных камер
DevList = mvsdk.CameraEnumerateDevice()
nDev = len(DevList)
if nDev < 1:
print("Камеры не обнаружены!")
return
# Вывод списка доступных камер
for i, DevInfo in enumerate(DevList):
print("{}: {} {}".format(i, DevInfo.GetFriendlyName(), DevInfo.GetPortType()))
# Автоматический выбор камеры, если она только одна
i = 0 if nDev == 1 else int(input("Выберите камеру: "))
DevInfo = DevList[i]
print(f"Выбрана камера: {DevInfo.GetFriendlyName()}")
# Инициализация камеры
hCamera = 0
try:
hCamera = mvsdk.CameraInit(DevInfo, -1, -1)
except mvsdk.CameraException as e:
print("Ошибка инициализации камеры ({}): {}".format(e.error_code, e.message))
return
# Получение параметров камеры
cap = mvsdk.CameraGetCapability(hCamera)
# Вывод информации о возможностях камеры
print_capability(cap)
# Буферы для хранения данных изображения
pFrameBuffer = None
pRawData = None
try:
# Сначала получим текущие параметры экспозиции
ae_state = mvsdk.CameraGetAeState(hCamera)
exposure_time = mvsdk.CameraGetExposureTime(hCamera)
print(f"Текущее состояние автоэкспозиции: {'Включено' if ae_state else 'Выключено'}")
print(f"Текущее время экспозиции: {exposure_time} мкс")
# Выбор режима работы камеры
# В нашем случае просто используем текущие настройки экспозиции
# Отключение триггерного режима (непрерывная съемка)
mvsdk.CameraSetTriggerMode(hCamera, 0)
# Поиск 12-битного цветного формата среди доступных
color12_format_index = None
for i in range(cap.iMediaTypeDesc):
desc = cap.pMediaTypeDesc[i]
desc_text = desc.GetDescription()
if "12" in desc_text and any(pattern in desc_text for pattern in ["Bayer", "RGB", "Color"]):
color12_format_index = i
print(f"Найден 12-битный цветной формат: {desc_text} (индекс {i})")
break
if color12_format_index is not None:
# Установка найденного 12-битного формата
mvsdk.CameraSetMediaType(hCamera, color12_format_index)
else:
print("12-битный цветной формат не найден, используется формат по умолчанию")
# Проверка текущего формата
current_media_type = mvsdk.CameraGetMediaType(hCamera)
print(f"Текущий формат: {current_media_type}")
# Получим текущий байеровский паттерн
current_media_type_desc = cap.pMediaTypeDesc[current_media_type]
bayer_type = current_media_type_desc.iMediaType
bayer_pattern = determine_bayer_pattern(bayer_type)
print(f"Паттерн Байера: {bayer_pattern}")
# Установка формата вывода ISP для цветной камеры (RGB24)
mvsdk.CameraSetIspOutFormat(hCamera, mvsdk.CAMERA_MEDIA_TYPE_RGB8)
current_isp_format = mvsdk.CameraGetIspOutFormat(hCamera)
print(f"Текущий формат ISP: 0x{current_isp_format:X}")
# Запуск камеры
mvsdk.CameraPlay(hCamera)
# Расчет размера буфера (для RGB24)
buffer_size = cap.sResolutionRange.iWidthMax * cap.sResolutionRange.iHeightMax * 3
pFrameBuffer = mvsdk.CameraAlignMalloc(buffer_size, 16)
# Захват кадра
print("Ожидание кадра...")
pRawData, FrameHead = mvsdk.CameraGetImageBuffer(hCamera, 3000)
print(f"Получен кадр формата: 0x{FrameHead.uiMediaType:X}")
# Вывод подробной информации о кадре
print_frame_info(FrameHead)
# Создадим папку для сохранения, если её нет
output_dir = "./output"
os.makedirs(output_dir, exist_ok=True)
# Генерируем имя файла с временной меткой
timestamp = time.strftime("%Y%m%d_%H%M%S")
# Метаданные для правильной интерпретации файлов
metadata = {
'width': FrameHead.iWidth,
'height': FrameHead.iHeight,
'exposure_time_us': FrameHead.uiExpTime,
'analog_gain': FrameHead.fAnalogGain,
'r_gain': FrameHead.fRgain,
'g_gain': FrameHead.fGgain,
'b_gain': FrameHead.fBgain,
'timestamp': timestamp,
'bits': 12,
'bytes_per_pixel': 1.5, # 12-бит упакованный = 1.5 байта на пиксель
'bayer_pattern': bayer_pattern,
'format': f"0x{FrameHead.uiMediaType:X}"
}
# Сохранение метаданных
metadata_path = os.path.join(output_dir, f"metadata_{timestamp}.json")
with open(metadata_path, 'w') as f:
json.dump(metadata, f, indent=4)
print(f"Метаданные сохранены в {metadata_path}")
# Сохранение исходного RAW изображения (12-битное цветное)
raw_filename = f"raw12_{timestamp}.raw"
raw_path = os.path.join(output_dir, raw_filename)
raw_status = mvsdk.CameraSaveImage(hCamera, raw_path.encode('utf-8'),
pRawData, FrameHead, mvsdk.FILE_RAW, 100)
print(f"Сохранение 12-бит RAW: {'успешно' if raw_status == mvsdk.CAMERA_STATUS_SUCCESS else f'ошибка {raw_status}'}")
# Обработка изображения через ISP (демозаикинг)
isp_status = mvsdk.CameraImageProcess(hCamera, pRawData, pFrameBuffer, FrameHead)
print(f"Обработка изображения ISP: {'успешно' if isp_status == mvsdk.CAMERA_STATUS_SUCCESS else f'ошибка {isp_status}'}")
# Преобразование RGB буфера в изображение numpy
frame_width = FrameHead.iWidth
frame_height = FrameHead.iHeight
# Создаем массив NumPy, указывающий на область памяти RGB данных
buffer_ptr = ctypes.cast(pFrameBuffer, ctypes.POINTER(ctypes.c_ubyte))
buffer_size = frame_width * frame_height * 3 # RGB = 3 байта на пиксель
# Создаем np.ndarray, который ссылается на данные в buffer_ptr
rgb_data = np.ctypeslib.as_array(buffer_ptr, shape=(buffer_size,))
# Копируем данные для безопасности
rgb_data = np.copy(rgb_data)
# Преобразуем в 3D RGB массив
rgb_image = rgb_data.reshape((frame_height, frame_width, 3))
# Возможно потребуется изменить порядок каналов BGR -> RGB для OpenCV
# rgb_image = cv2.cvtColor(rgb_image, cv2.COLOR_BGR2RGB)
# Сохраняем обработанное RGB изображение в различных форматах
# Сохранение в PNG (8-бит на канал)
png_filename = f"rgb_{timestamp}.png"
png_path = os.path.join(output_dir, png_filename)
cv2.imwrite(png_path, rgb_image)
print(f"Сохранение RGB PNG: файл {png_path} создан")
# Сохранение в TIFF (16-бит на канал)
# Масштабируем 8-бит (0-255) до 16-бит (0-65535)
rgb_image_16bit = (rgb_image.astype(np.uint16) * 257)
tiff_filename = f"rgb16_{timestamp}.tiff"
tiff_path = os.path.join(output_dir, tiff_filename)
cv2.imwrite(tiff_path, rgb_image_16bit)
print(f"Сохранение RGB TIFF (16-бит): файл {tiff_path} создан")
# Создаем текстовый файл с инструкцией по открытию в ImageJ
instructions = """
Инструкция по открытию файлов в ImageJ:
1. Открытие 12-бит RAW файла:
- File > Import > Raw...
- Выберите файл raw12_*.raw
- В диалоге укажите:
- Width: {width}
- Height: {height}
- Offset to first image: 0
- Number of images: 1
- Gap between images: 0
- Little-endian byte order: отметьте, если ваша система использует little-endian
- Для неупакованного 12-бит: "16-bit Unsigned"
- Для упакованного 12-бит необходимо использовать специальные плагины
2. Открытие 16-бит TIFF файла:
- File > Open...
- Выберите файл rgb16_*.tiff
- Откроется автоматически как 16-бит RGB
3. Для цветного 12-бит RAW необходимо провести демозаикинг:
- После открытия RAW используйте Plugins > Color > Demosaic...
- Выберите соответствующий паттерн Байера: {bayer_pattern}
4. Для упакованных 12-бит RAW (если формат 12-bit Packed):
- Рекомендуется использовать дополнительные утилиты от производителя камеры
- Альтернатива: предварительная обработка в другой программе с последующим импортом как 16-бит TIFF
Параметры съемки:
- Время экспозиции: {exposure_time} мкс
- Аналоговое усиление: {analog_gain}
""".format(
width=FrameHead.iWidth,
height=FrameHead.iHeight,
bayer_pattern=bayer_pattern,
exposure_time=FrameHead.uiExpTime,
analog_gain=FrameHead.fAnalogGain
)
instructions_filename = f"imagej_instructions_{timestamp}.txt"
instructions_path = os.path.join(output_dir, instructions_filename)
with open(instructions_path, 'w') as f:
f.write(instructions)
print(f"Инструкции по открытию в ImageJ сохранены в {instructions_path}")
# Выводим информацию о созданных файлах
print("\nСозданные файлы:")
created_files = [raw_filename, png_filename, tiff_filename,
f"metadata_{timestamp}.json", f"imagej_instructions_{timestamp}.txt"]
for filename in created_files:
path = os.path.join(output_dir, filename)
if os.path.exists(path):
file_size = os.path.getsize(path)
print(f"{path}: {file_size} байт")
# Освобождение буфера изображения
mvsdk.CameraReleaseImageBuffer(hCamera, pRawData)
except mvsdk.CameraException as e:
print(f"Ошибка камеры ({e.error_code}): {e.message}")
except Exception as e:
print(f"Общая ошибка: {e}")
import traceback
traceback.print_exc()
finally:
# Остановка и освобождение ресурсов
if hCamera > 0:
mvsdk.CameraStop(hCamera)
mvsdk.CameraUnInit(hCamera)
if pFrameBuffer is not None:
try:
mvsdk.CameraAlignFree(pFrameBuffer)
except:
pass
print("Камера остановлена и ресурсы освобождены")
def determine_bayer_pattern(media_type):
"""Определяет паттерн Байера на основе кода формата медиа"""
# Словарь соответствия кодов формата и паттернов Байера
bayer_patterns = {
# Коды из SDK
mvsdk.CAMERA_MEDIA_TYPE_BAYGR8: "GRBG",
mvsdk.CAMERA_MEDIA_TYPE_BAYRG8: "RGGB",
mvsdk.CAMERA_MEDIA_TYPE_BAYGB8: "GBRG",
mvsdk.CAMERA_MEDIA_TYPE_BAYBG8: "BGGR",
mvsdk.CAMERA_MEDIA_TYPE_BAYGR10_MIPI: "GRBG",
mvsdk.CAMERA_MEDIA_TYPE_BAYRG10_MIPI: "RGGB",
mvsdk.CAMERA_MEDIA_TYPE_BAYGB10_MIPI: "GBRG",
mvsdk.CAMERA_MEDIA_TYPE_BAYBG10_MIPI: "BGGR",
mvsdk.CAMERA_MEDIA_TYPE_BAYGR10: "GRBG",
mvsdk.CAMERA_MEDIA_TYPE_BAYRG10: "RGGB",
mvsdk.CAMERA_MEDIA_TYPE_BAYGB10: "GBRG",
mvsdk.CAMERA_MEDIA_TYPE_BAYBG10: "BGGR",
mvsdk.CAMERA_MEDIA_TYPE_BAYGR12: "GRBG",
mvsdk.CAMERA_MEDIA_TYPE_BAYRG12: "RGGB",
mvsdk.CAMERA_MEDIA_TYPE_BAYGB12: "GBRG",
mvsdk.CAMERA_MEDIA_TYPE_BAYBG12: "BGGR",
mvsdk.CAMERA_MEDIA_TYPE_BAYGR12_PACKED: "GRBG",
mvsdk.CAMERA_MEDIA_TYPE_BAYRG12_PACKED: "RGGB",
mvsdk.CAMERA_MEDIA_TYPE_BAYGB12_PACKED: "GBRG",
mvsdk.CAMERA_MEDIA_TYPE_BAYBG12_PACKED: "BGGR",
mvsdk.CAMERA_MEDIA_TYPE_BAYGR16: "GRBG",
mvsdk.CAMERA_MEDIA_TYPE_BAYRG16: "RGGB",
mvsdk.CAMERA_MEDIA_TYPE_BAYGB16: "GBRG",
mvsdk.CAMERA_MEDIA_TYPE_BAYBG16: "BGGR",
}
if media_type in bayer_patterns:
return bayer_patterns[media_type]
else:
# Если не можем определить, возвращаем наиболее распространенный
return "RGGB"
def print_frame_info(FrameHead):
"""Выводит подробную информацию о кадре"""
print(f"Формат: 0x{FrameHead.uiMediaType:X}")
print(f"Размер буфера: {FrameHead.uBytes} байт")
print(f"Размеры: {FrameHead.iWidth}x{FrameHead.iHeight}")
print(f"Время экспозиции: {FrameHead.uiExpTime} мкс")
print(f"Аналоговое усиление: {FrameHead.fAnalogGain}")
if FrameHead.fRgain > 0 or FrameHead.fGgain > 0 or FrameHead.fBgain > 0:
print(f"RGB усиление: R={FrameHead.fRgain}, G={FrameHead.fGgain}, B={FrameHead.fBgain}")
def print_capability(cap):
"""Выводит информацию о возможностях камеры"""
print("\n=== ВОЗМОЖНОСТИ КАМЕРЫ ===")
# Проверка на монохромную камеру
if cap.sIspCapacity.bMonoSensor:
print("Тип камеры: Монохромная (черно-белая)")
else:
print("Тип камеры: Цветная")
# Доступные форматы
print("\nДоступные форматы данных:")
for i in range(cap.iMediaTypeDesc):
desc = cap.pMediaTypeDesc[i]
media_type_code = desc.iMediaType
print(f" {i}: {desc.GetDescription()} (код: 0x{media_type_code:X})")
if "Bayer" in desc.GetDescription() or "RGB" in desc.GetDescription():
bayer_pattern = determine_bayer_pattern(media_type_code)
print(f" Паттерн Байера: {bayer_pattern}")
# Доступные размеры
print("\nДоступные размеры изображения:")
for i in range(cap.iImageSizeDesc):
desc = cap.pImageSizeDesc[i]
print(f" {i}: {desc.GetDescription()} - {desc.iWidth}x{desc.iHeight}")
print("\nДиапазон возможных разрешений:")
print(f" Ширина: {cap.sResolutionRange.iWidthMin} - {cap.sResolutionRange.iWidthMax}")
print(f" Высота: {cap.sResolutionRange.iHeightMin} - {cap.sResolutionRange.iHeightMax}")
# Режимы триггера
print("\nДоступные режимы запуска:")
for i in range(cap.iTriggerDesc):
desc = cap.pTriggerDesc[i]
print(f" {i}: {desc.GetDescription()}")
print("===========================\n")
if __name__ == "__main__":
main()Editor is loading...
Leave a Comment