Exposure编译失败的原因总结

本文讲述了在CMake编译完成后,如何解决因未将moc_MainWindow.cxx文件添加到工程Generated目录导致的链接错误,确保正确链接QMetaObject。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

注意问题一:
在cmake编译好以后,记得手动把编译文件中的moc_MainWindow.cxx添加到工程的Generated里面,否则会提示

MainWindow.obj:error LNK2001: 无法解析的外部符号 "public: virtual struct QMetaObject const * __thiscall
import sys import cv2 import numpy as np import time import os import threading import json from datetime import datetime from ctypes import * from MvImport.MvErrorDefine_const import MV_OK sys.path.append("C:\\Program Files (x86)\\MVS\\Development\\Samples\\Python\\MvImport") from MvImport.MvCameraControl_class import * from MvImport.CamOperation_class import CameraOperation # 全局变量 takephoto = False # 拍照触发标志 camera_lock = threading.Lock() # 相机操作锁 stop_flag = False # 程序停止标志 global deviceList # class HikCamera: # def __init__(self): # self.cam = None # self.data_buf = None # self.nPayloadSize = 0 # self.initialized = False # # def initialize(self): # """初始化相机""" # try: # # 枚举设备 # deviceList = MV_CC_DEVICE_INFO_LIST() # tlayerType = MV_GIGE_DEVICE | MV_USB_DEVICE # ret = MvCamera.MV_CC_EnumDevices(tlayerType, deviceList) # if deviceList.nDeviceNum == 0: # print("错误:未检测到相机设备!") # return False # # # 创建相机实例 # self.cam = MvCamera() # stDeviceInfo = cast(deviceList.pDeviceInfo[0], POINTER(MV_CC_DEVICE_INFO)).contents # ret = self.cam.MV_CC_CreateHandle(stDeviceInfo) # if ret != 0: # print(f"创建相机句柄失败,错误码: {ret}") # return False # # # 打开设备 # ret = self.cam.MV_CC_OpenDevice(MV_ACCESS_Exclusive, 0) # if ret != 0: # print(f"打开相机失败,错误码: {ret}") # return False # # # 配置相机参数 # # 设置连续采集模式 # ret = self.cam.MV_CC_SetEnumValue("TriggerMode", MV_TRIGGER_MODE_OFF) # if ret != 0: # print(f"设置连续采集模式失败,错误码: {ret}") # # # 设置自动曝光 # ret = self.cam.MV_CC_SetEnumValue("ExposureAuto", 1) # 1=连续自动曝光 # if ret != 0: # print(f"设置自动曝光失败,错误码: {ret}") # # 尝试手动设置曝光 # self.cam.MV_CC_SetFloatValue("ExposureTime", 9000.0) # 10ms # # # 设置自动增益 # ret = self.cam.MV_CC_SetEnumValue("GainAuto", 1) # 1=连续自动增益 # if ret != 0: # print(f"设置自动增益失败,错误码: {ret}") # self.cam.MV_CC_SetFloatValue("Gain", 12.0) # 12dB增益 # # # 获取有效载荷大小 # stParam = MVCC_INTVALUE() # self.cam.MV_CC_GetIntValue("PayloadSize", stParam) # self.nPayloadSize = stParam.nCurValue # self.data_buf = (c_ubyte * self.nPayloadSize)() # # # 开始取流 # ret = self.cam.MV_CC_StartGrabbing() # if ret != 0: # print(f"开始取流失败,错误码: {ret}") # return False # # self.initialized = True # print("相机初始化成功") # return True # # except Exception as e: # print(f"相机初始化异常: {str(e)}") # return False # # def capture_image(self): # """捕获一帧图像""" # if not self.initialized: # print("相机未初始化") # return None # # try: # # 获取一帧数据 # stFrameInfo = MV_FRAME_OUT_INFO_EX() # ret = self.cam.MV_CC_GetOneFrameTimeout(self.data_buf, self.nPayloadSize, stFrameInfo, 1000) # # if ret != 0: # print(f"获取帧失败,错误码: {ret}") # return None # # # 直接处理BGR格式 # if stFrameInfo.enPixelType == PixelType_Gvsp_BGR8_Packed: # img = np.frombuffer(self.data_buf, dtype=np.uint8, count=stFrameInfo.nFrameLen) # img = img.reshape((stFrameInfo.nHeight, stFrameInfo.nWidth, 3)) # return img # # # 尝试转换其他格式 # convert_param = MV_CC_PIXEL_CONVERT_PARAM() # memset(byref(convert_param), 0, sizeof(convert_param)) # # # 关键修复:计算目标缓冲区大小 # nDstBufferSize = stFrameInfo.nWidth * stFrameInfo.nHeight * 3 + 2048 # 额外增加2KB缓冲区 # pDstBuffer = (c_ubyte * nDstBufferSize)() # # # 设置转换参数 # convert_param.nWidth = stFrameInfo.nWidth # convert_param.nHeight = stFrameInfo.nHeight # convert_param.pSrcData = self.data_buf # convert_param.nSrcDataLen = stFrameInfo.nFrameLen # convert_param.enSrcPixelType = stFrameInfo.enPixelType # convert_param.enDstPixelType = PixelType_Gvsp_BGR8_Packed # convert_param.pDstBuffer = cast(pDstBuffer, POINTER(c_ubyte)) # convert_param.nDstBufferSize = nDstBufferSize # # ret_convert = self.cam.MV_CC_ConvertPixelType(convert_param) # # if ret_convert == 0 and convert_param.nDstLen > 0: # img = np.frombuffer(pDstBuffer, dtype=np.uint8, count=convert_param.nDstLen) # img = img.reshape((stFrameInfo.nHeight, stFrameInfo.nWidth, 3)) # return img # else: # print(f"图像转换失败,错误码: {ret_convert}") # print(f"源格式: {stFrameInfo.enPixelType}, 目标大小: {convert_param.nDstLen}/{nDstBufferSize}") # return None # # except Exception as e: # print(f"捕获图像异常: {str(e)}") # return None # def release(self): # """释放相机资源""" # if self.initialized: # try: # self.cam.MV_CC_StopGrabbing() # self.cam.MV_CC_CloseDevice() # print("相机资源已释放") # except: # print("释放相机资源时出错") # finally: # self.initialized = False # 获取选取设备信息的索引,通过[]之间的字符去解析 def TxtWrapBy(start_str, end, all): start = all.find(start_str) if start >= 0: start += len(start_str) end = all.find(end, start) if end >= 0: return all[start:end].strip() # 将返回的错误码转换为十六进制显示 def ToHexStr(num): chaDic = {10: 'a', 11: 'b', 12: 'c', 13: 'd', 14: 'e', 15: 'f'} hexStr = "" if num < 0: num = num + 2 ** 32 while num >= 16: digit = num % 16 hexStr = chaDic.get(digit, str(digit)) + hexStr num //= 16 hexStr = chaDic.get(num, str(num)) + hexStr return hexStr def decoding_char(c_ubyte_value): c_char_p_value = ctypes.cast(c_ubyte_value, ctypes.c_char_p) try: decode_str = c_char_p_value.value.decode('gbk') # Chinese characters except UnicodeDecodeError: decode_str = str(c_char_p_value.value) return decode_str class HikCamera: def __init__(self, device_index=0): # 添加设备索引参数 self.cam = None self.data_buf = None self.nPayloadSize = 0 self.initialized = False self.device_index = device_index # 保存设备索引\ self.initialize(device_index) self.cam_op = None def enum_devices(self): global obj_cam_operation deviceList = MV_CC_DEVICE_INFO_LIST() n_layer_type = (MV_GIGE_DEVICE | MV_USB_DEVICE | MV_GENTL_CAMERALINK_DEVICE | MV_GENTL_CXP_DEVICE | MV_GENTL_XOF_DEVICE) ret = MvCamera.MV_CC_EnumDevices(n_layer_type, deviceList) if ret != 0: strError = "Enum devices fail! ret = :" + ToHexStr(ret) return ret if deviceList.nDeviceNum == 0: return ret print("Find %d devices!" % deviceList.nDeviceNum) devList = [] for i in range(0, deviceList.nDeviceNum): mvcc_dev_info = cast(deviceList.pDeviceInfo[i], POINTER(MV_CC_DEVICE_INFO)).contents if mvcc_dev_info.nTLayerType == MV_GIGE_DEVICE or mvcc_dev_info.nTLayerType == MV_GENTL_GIGE_DEVICE: print("\ngige device: [%d]" % i) user_defined_name = decoding_char(mvcc_dev_info.SpecialInfo.stGigEInfo.chUserDefinedName) model_name = decoding_char(mvcc_dev_info.SpecialInfo.stGigEInfo.chModelName) print("device user define name: " + user_defined_name) print("device model name: " + model_name) nip1 = ((mvcc_dev_info.SpecialInfo.stGigEInfo.nCurrentIp & 0xff000000) >> 24) nip2 = ((mvcc_dev_info.SpecialInfo.stGigEInfo.nCurrentIp & 0x00ff0000) >> 16) nip3 = ((mvcc_dev_info.SpecialInfo.stGigEInfo.nCurrentIp & 0x0000ff00) >> 8) nip4 = (mvcc_dev_info.SpecialInfo.stGigEInfo.nCurrentIp & 0x000000ff) print("current ip: %d.%d.%d.%d " % (nip1, nip2, nip3, nip4)) devList.append( "[" + str(i) + "]GigE: " + user_defined_name + " " + model_name + "(" + str(nip1) + "." + str( nip2) + "." + str(nip3) + "." + str(nip4) + ")") return deviceList def open_device(self, deviceList, nSelCamIndex): global obj_cam_operation cam = MvCamera() # 实例化 if nSelCamIndex < 0: return MV_E_CALLORDER obj_cam_operation = CameraOperation(cam, deviceList, nSelCamIndex) # 实例化相机操作类 ret = obj_cam_operation.Open_device() if 0 != ret: strError = "Open device failed ret:" + ToHexStr(ret) return obj_cam_operation def initialize(self, device_index): # 加载一个json文件(相机id,ip,name,mfs path) with open('config/settings.json', 'r', encoding='utf-8') as f: # 注意文件路径 settings = json.load(f) # 解析 JSON 为 Python 字典 # 根据传入的相机ID加载path path = settings[str(device_index)]['path'] # 搜索相机列表 deviceList = self.enum_devices() # 打开相机 # 1.实例化一个相机 # 2.实例化相机操作类(cam, list, index) self.cam_op = self.open_device(deviceList, device_index) # 设置相机参数 self.cam_op.cam_settings(path) self.initialized = True # ret = obj_cam_operation.Open_device() # # 加载参数 # if 0 != ret: # print(f"打开相机失败,错误码: {ret}") # return False # ret = self.cam.MV_CC_FeatureLoad("mfs path") # if MV_OK != ret: # print("load feature fail! ret [0x%x]" % ret) # print("finish import the camera properties from the file") # self.initialized = True # try: # # 枚举设备 # deviceList = MV_CC_DEVICE_INFO_LIST() # tlayerType = MV_GIGE_DEVICE | MV_USB_DEVICE # ret = MvCamera.MV_CC_EnumDevices(tlayerType, deviceList) # if deviceList.nDeviceNum == 0: # print("错误:未检测到相机设备!") # return False # # # 检查设备索引是否有效 # if self.device_index >= deviceList.nDeviceNum: # print(f"错误:设备索引{self.device_index}超出范围,最大设备数={deviceList.nDeviceNum}") # return False # # # 创建相机实例(使用指定的设备索引) # self.cam = MvCamera() # stDeviceInfo = cast(deviceList.pDeviceInfo[self.device_index], POINTER(MV_CC_DEVICE_INFO)).contents # ret = self.cam.MV_CC_CreateHandle(stDeviceInfo) # if ret != 0: # print(f"创建相机{self.device_index}句柄失败,错误码: {ret}") # return False # # # 打开设备 # ret = self.cam.MV_CC_OpenDevice(MV_ACCESS_Exclusive, 0) # if ret != 0: # print(f"打开相机失败,错误码: {ret}") # return False # # # 配置相机参数 # # 设置连续采集模式 # ret = self.cam.MV_CC_SetEnumValue("TriggerMode", MV_TRIGGER_MODE_OFF) # if ret != 0: # print(f"设置连续采集模式失败,错误码: {ret}") # # # 设置自动曝光 # ret = self.cam.MV_CC_SetEnumValue("ExposureAuto", 1) # 1=连续自动曝光 # if ret != 0: # print(f"设置自动曝光失败,错误码: {ret}") # # 尝试手动设置曝光 # self.cam.MV_CC_SetFloatValue("ExposureTime", 9000.0) # 10ms # # # 设置自动增益 # ret = self.cam.MV_CC_SetEnumValue("GainAuto", 1) # 1=连续自动增益 # if ret != 0: # print(f"设置自动增益失败,错误码: {ret}") # self.cam.MV_CC_SetFloatValue("Gain", 12.0) # 12dB增益 # # # 获取有效载荷大小 # stParam = MVCC_INTVALUE() # self.cam.MV_CC_GetIntValue("PayloadSize", stParam) # self.nPayloadSize = stParam.nCurValue # self.data_buf = (c_ubyte * self.nPayloadSize)() # # # 开始取流 # ret = self.cam.MV_CC_StartGrabbing() # if ret != 0: # print(f"开始取流失败,错误码: {ret}") # return False # # self.initialized = True # print(f"相机{self.device_index}初始化成功") # return True # # except Exception as e: # print(f"相机{self.device_index}初始化异常: {str(e)}") # return False def capture_image(self): """捕获一帧图像""" if not self.initialized: print("相机未初始化") return None try: # 获取一帧数据 stFrameInfo = MV_FRAME_OUT_INFO_EX() ret = self.cam.MV_CC_GetOneFrameTimeout(self.data_buf, self.nPayloadSize, stFrameInfo, 1000) if ret != 0: print(f"获取帧失败,错误码: {ret}") return None # 直接处理BGR格式 if stFrameInfo.enPixelType == PixelType_Gvsp_BGR8_Packed: img = np.frombuffer(self.data_buf, dtype=np.uint8, count=stFrameInfo.nFrameLen) img = img.reshape((stFrameInfo.nHeight, stFrameInfo.nWidth, 3)) return img # 尝试转换其他格式 convert_param = MV_CC_PIXEL_CONVERT_PARAM() memset(byref(convert_param), 0, sizeof(convert_param)) # 关键修复:计算目标缓冲区大小 nDstBufferSize = stFrameInfo.nWidth * stFrameInfo.nHeight * 3 + 2048 # 额外增加2KB缓冲区 pDstBuffer = (c_ubyte * nDstBufferSize)() # 设置转换参数 convert_param.nWidth = stFrameInfo.nWidth convert_param.nHeight = stFrameInfo.nHeight convert_param.pSrcData = self.data_buf convert_param.nSrcDataLen = stFrameInfo.nFrameLen convert_param.enSrcPixelType = stFrameInfo.enPixelType convert_param.enDstPixelType = PixelType_Gvsp_BGR8_Packed convert_param.pDstBuffer = cast(pDstBuffer, POINTER(c_ubyte)) convert_param.nDstBufferSize = nDstBufferSize ret_convert = self.cam.MV_CC_ConvertPixelType(convert_param) if ret_convert == 0 and convert_param.nDstLen > 0: img = np.frombuffer(pDstBuffer, dtype=np.uint8, count=convert_param.nDstLen) img = img.reshape((stFrameInfo.nHeight, stFrameInfo.nWidth, 3)) return img else: print(f"图像转换失败,错误码: {ret_convert}") print(f"源格式: {stFrameInfo.enPixelType}, 目标大小: {convert_param.nDstLen}/{nDstBufferSize}") return None except Exception as e: print(f"捕获图像异常: {str(e)}") return None def release(self): """释放相机资源""" if self.initialized: try: self.cam.MV_CC_StopGrabbing() self.cam.MV_CC_CloseDevice() print("相机资源已释放") except: print("释放相机资源时出错") finally: self.initialized = False def timer1_thread(): """定时器线程,每分钟设置一次拍照标志""" global takephoto while not stop_flag: # 每分钟触发一次拍照 time.sleep(30) takephoto = True print(f"[{datetime.now().strftime('%H:%M:%S')}] 触发拍照标志") # def timer2_thread(): # """定时器线程,每分钟设置一次拍照标志""" # global takephoto # while not stop_flag: # # 每分钟触发一次拍照 # time.sleep(30) # takephoto = True # print(f"[{datetime.now().strftime('%H:%M:%S')}] 触发拍照标志") def photo_task(output_dir1, output_dir2): """拍照任务处理线程""" global takephoto camera1 = HikCamera(device_index=0) # camera2 = HikCamera(device_index=1) # 确保输出目录存在 os.makedirs(output_dir1, exist_ok=True) # os.makedirs(output_dir2, exist_ok=True) while not stop_flag: if takephoto: with camera_lock: takephoto = False # 重置标志 # # 初始化相机(如果需要) # if not camera1.initialized and camera2.initialized: # if not camera1.initialize() and camera2.initialized: # print("无法初始化相机,跳过本次拍照") # continue # 捕获图像 print("开始捕获图像...") img1 = camera1.capture_image() # img2 = camera2.capture_image() # if img1 and img2 is not None: if img1 is not None: # 生成文件名 timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") filename1 = os.path.join(output_dir1, f"photo1_{timestamp}.jpg") # filename2 = os.path.join(output_dir2, f"photo2_{timestamp}.jpg") # 保存图像 cv2.imwrite(filename1, img1) # cv2.imwrite(filename2, img2) # print(f"照片已保存至: {filename1, filename2}") print(f"照片已保存至: {filename1}") else: print("捕获图像失败") # 短暂延迟,避免过于频繁访问标志位 time.sleep(0.1) # 短暂睡眠以降低CPU占用 time.sleep(0.1) # 释放相机资源 camera1.release() # camera2.release() if __name__ == "__main__": # 配置参数 output_directory1 = "C:/Users/25770/Desktop/photo1" # 更改为你的存储路径 output_directory2 = "C:/Users/25770/Desktop/photo2" # 更改为你的存储路径 # # # # 索引相机 # # ch:初始化SDK | en: initialize SDK # MvCamera.MV_CC_Initialize() # # deviceList = MV_CC_DEVICE_INFO_LIST() # tlayerType = MV_GIGE_DEVICE | MV_USB_DEVICE # 创建并启动线程 timer1 = threading.Thread(target=timer1_thread, daemon=True) photo_processor = threading.Thread(target=photo_task, args=(output_directory1, output_directory2), daemon=True) timer1.start() photo_processor.start() try: # 主线程保持运行 while True: time.sleep(1) except KeyboardInterrupt: print("程序被用户中断") stop_flag = True timer1.join() photo_processor.join() print("程序已退出") 运行后报错: gige device: [0] device user define name: device model name: MV-CS050-10GC current ip: 169.254.199.38 open device successfully! finish import the camera properties from the file [13:56:48] 触发拍照标志 开始捕获图像... 捕获图像异常: 'NoneType' object has no attribute 'MV_CC_GetOneFrameTimeout' 捕获图像失败
最新发布
07-03
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Dezeming

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值