用Python opencvCall industrial camera frame differential method for dynamically tracking,The code can run successfully but the rectangular box drawing not to come out,
import cv2
import numpy as np
import mvsdk
import platform
class Camera(object):
def init(self, DevInfo):
super(Camera, self).init()
self.DevInfo = DevInfo
self.hCamera = 0
self.cap = None
self.pFrameBuffer = 0
def open(self): if self.hCamera > 0: return True # 打開相機 hCamera = 0 try: hCamera = mvsdk.CameraInit(self.DevInfo, -1, -1) except mvsdk.CameraException as e: print("CameraInit Failed({}): {}".format(e.error_code, e.message)) return False # 獲取相機特性描述 cap = mvsdk.CameraGetCapability(hCamera) # 判斷是黑白相機還是彩色相機 monoCamera = (cap.sIspCapacity.bMonoSensor != 0) # 黑白相機讓ISP直接輸出MONO數據,而不是擴展成R=G=B的24位灰度 if monoCamera: mvsdk.CameraSetIspOutFormat(hCamera, mvsdk.CAMERA_MEDIA_TYPE_MONO8) else: mvsdk.CameraSetIspOutFormat(hCamera, mvsdk.CAMERA_MEDIA_TYPE_BGR8) # 計算RGB buffer所需的大小,這裡直接按照相機的最大分辨率來分配 FrameBufferSize = cap.sResolutionRange.iWidthMax * cap.sResolutionRange.iHeightMax * (1 if monoCamera else 3) # 分配RGB buffer,用來存放ISP輸出的圖像 # 備注:從相機傳輸到PC端的是RAW數據,在PC端通過軟件ISP轉為RGB數據(如果是黑白相機就不需要轉換格式,但是ISP還有其它處理,所以也需要分配這個buffer) pFrameBuffer = mvsdk.CameraAlignMalloc(FrameBufferSize, 16) # 相機模式切換成連續采集 mvsdk.CameraSetTriggerMode(hCamera, 0) # 手動曝光,曝光時間30ms mvsdk.CameraSetAeState(hCamera, 0) mvsdk.CameraSetExposureTime(hCamera, 30 * 1000) # 讓SDK內部取圖線程開始工作 mvsdk.CameraPlay(hCamera) self.hCamera = hCamera self.pFrameBuffer = pFrameBuffer self.cap = cap return Truedef close(self): if self.hCamera > 0: mvsdk.CameraUnInit(self.hCamera) self.hCamera = 0 mvsdk.CameraAlignFree(self.pFrameBuffer) self.pFrameBuffer = 0def grab(self): # Images from the camera take a frame hCamera = self.hCamera pFrameBuffer = self.pFrameBuffer try: pRawData, FrameHead = mvsdk.CameraGetImageBuffer(hCamera, 200) mvsdk.CameraImageProcess(hCamera, pRawData, pFrameBuffer, FrameHead) mvsdk.CameraReleaseImageBuffer(hCamera, pRawData) # windowsThe pick up to the image data is upside down,以BMP格式存放.轉換成opencvYou need to flip up and down into a positive # linuxUnder the direct output is,Don't need to flip up and down if platform.system() == "Windows": mvsdk.CameraFlipFrameBuffer(pFrameBuffer, FrameHead, 1) # 此時圖片已經存儲在pFrameBuffer中,對於彩色相機pFrameBuffer=RGB數據,黑白相機pFrameBuffer=8位灰度數據 # 把pFrameBuffer轉換成opencv的圖像格式以進行後續算法處理 frame_data = (mvsdk.c_ubyte * FrameHead.uBytes).from_address(pFrameBuffer) frame = np.frombuffer(frame_data, dtype=np.uint8) frame = frame.reshape((FrameHead.iHeight, FrameHead.iWidth, 1 if FrameHead.uiMediaType == mvsdk.CAMERA_MEDIA_TYPE_MONO8 else 3)) return frame except mvsdk.CameraException as e: if e.error_code != mvsdk.CAMERA_STATUS_TIME_OUT: print("CameraGetImageBuffer failed({}): {}".format(e.error_code, e.message)) return None
def main_loop():
# 枚舉相機
DevList = mvsdk.CameraEnumerateDevice()
nDev = len(DevList)
if nDev < 1:
print("No camera was found!")
return
for i, DevInfo in enumerate(DevList): print("{}: {} {}".format(i, DevInfo.GetFriendlyName(), DevInfo.GetPortType()))cams = []for i in range(2): cam = Camera(DevList[i]) if cam.open(): cams.append(cam)while (cv2.waitKey(1) & 0xFF) != ord('q'): for cam in cams: frame = cam.grab() if frame is not None: frame = cv2.resize(frame, (640, 480), interpolation=cv2.INTER_LINEAR) frame = process_frame(frame) cv2.imshow("{} Press q to end".format(cam.DevInfo.GetFriendlyName()), frame)
def process_frame(frame):
es = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (9, 4)) # 返回指定形狀和尺寸的結構元素,橢圓形,中心點
kernel = np.ones((5, 5), np.uint8) # 返回矩陣
background = None
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (21, 21), 0)
# 將第一幀設置為整個輸入的背景background = gray# For each read from the background frame is calculated with the background of the differences between,並得到一個差分圖(different map).# Also need to apply the threshold to get a picture of a black and white images,And by the following code to expand(dilate)圖像,Thus the hole(hole)和缺陷(imperfection)進行歸一化處理diff = cv2.absdiff(background, gray)diff = cv2.threshold(diff, 148, 255, cv2.THRESH_BINARY)[ 1] # Threshold binarization processing of black and white,灰度圖,Classifying image threshold,最大值,Said if the pixel values greater than(有時小於)阈值則要給出的值,Decided to give different kinds of thresholddiff = cv2.dilate(diff, es, iterations=2) # 形態學膨脹,目標圖片,進行操作的內核,默認為3×3的矩陣,腐蝕次數,默認為1# 顯示矩形框contours, hierarchy = cv2.findContours(diff.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # The outline of the function to calculate an image in the target,Return the contour outside,# contours:返回的輪廓 hierarchy:每條輪廓對應的屬性for c in contours: if cv2.contourArea(c) < 1500: # Get outline area 對於矩形區域,Display only the outline is greater than the given threshold,So some small changes will not show.For constant light and low noise of camera is not set outline minimum size of the threshold continue (x, y, w, h) = cv2.boundingRect(c) # 該函數計算矩形的邊界框,x,y是矩陣左上點的坐標,w,h是矩陣的寬和高 cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)return frame
def main():
try:
main_loop()
finally:
cv2.destroyAllWindows()
main()