(一)、只进行canny边缘检测
效果图:
(原图)
(canny边缘检测后的图)
代码(Python3.6 + OpenCV3):
import cv2 import numpy as np img = cv2.imread("F:\python\data\photos\screenshot1.png",0) cv2.imwrite("creenshot1canny.jpg",cv2.Canny(img,200,300)) cv2.imshow("mycanny",cv2.imread("creenshot1canny.jpg")) cv2.waitKey() cv2.destroyAllWindows()
(二)滤波后使用canny边缘检测
(1)先使用medianBlur()作为模糊函数,去除噪声;
(2)将图像从BGR转成灰度图;
(3)使用Laplacian()作为边缘检测函数,产生明显的边缘线条;
(4)转换为黑色边缘和白色背景,归一化(像素0到1之间),并乘以源图像;
(5)canny边缘检测。
效果图:
(步骤(1)——(4)后效果图)
(步骤(5)效果图)
代码(Python3.6 + OpenCV3):
cameo.py
import cv2 import Opencv_test.filters from Opencv_test.managers import WindowManager, CaptureManager class Cameo(object): def __init__(self): self._windowManager = WindowManager('Camo', self.onKeypress) self._captureManager = CaptureManager(cv2.VideoCapture(0), self._windowManager, True) self._curveFilter = Opencv_test.filters.BGRPortraCurveFilter()#新增 def run(self): """运行main""" self._windowManager.createWindow() while self._windowManager.isWindowCreated: self._captureManager.enterFrame() frame = self._captureManager.frame Opencv_test.filters.strokeEdges(frame,frame)#新增 self._curveFilter.apply(frame,frame)#新增 self._captureManager.exitFrame() self._windowManager.processEvents() def onKeypress(self, keycode): """设置按键 空格 -> 截图 tab -> 开始/暂停视频截取 esc -> 退出窗口 """ if keycode == 32: # 空格 self._captureManager.writeImage('F:\python\data\photos\screenshot.png') elif keycode == 9: # tab if not self._captureManager.isWritingVideo: self._captureManager.startWritingVideo('F:\python\data\photos\screencast.avi') else: self._captureManager.stopWritingVideo() elif keycode == 27: # esc self._windowManager.destroyWindow() if __name__ == "__main__": Cameo().run()
managers.py
import cv2 import numpy import time class CaptureManager(object): def __init__(self, capture, previewWindowManager=None,shouldMirrorPreview=False): self.previewWindowManager = previewWindowManager self.shouldMirrorPreview = shouldMirrorPreview self._capture = capture self._channel = 0 self._enteredFrame = False self._frame = None self._imageFilename = None self._videoFilename = None self._videoEncoding = None self._videoWriter = None self._startTime = None self._framesElapsed = numpy.long(0) self._fpsEstimate = None @property def channel(self): return self._channel @channel.setter def channel(self, value): if self._channel != value: self._channel = value self._frame = None @property def frame(self): if self._enteredFrame and self._frame is None: _, self._frame = self._capture.retrieve() return self._frame @property def isWritingImage(self): return self._imageFilename is not None @property def isWritingVideo(self): return self._videoFilename is not None def enterFrame(self): """ 获取下一帧 """ #但首先检查以前的帧是否退出 assert not self._enteredFrame, 'previous enterFrame() had no matching exitFrame()' if self._capture is not None: self._enteredFrame = self._capture.grab() def exitFrame(self): """ 设置出窗口,写入文件,释放框架""" # 检查是否有抓取的框架是可检索的 if self.frame is None: self._enteredFrame = False return # 更新FPS估值和相关变量 if self._framesElapsed == 0: self._startTime = time.time() else: timeElapsed = time.time() - self._startTime self._fpsEstimate = self._framesElapsed / timeElapsed self._framesElapsed += 1 # 设置窗口。 if self.previewWindowManager is not None: if self.shouldMirrorPreview: mirroredFrame = numpy.fliplr(self._frame).copy() self.previewWindowManager.show(mirroredFrame) else: self.previewWindowManager.show(self._frame) # 写入图像文件 if self.isWritingImage: cv2.imwrite(self._imageFilename, self._frame) self._imageFilename = None # 写入视频文件 self._writeVideoFrame() # 释放框架 self._frame = None self._enteredFrame = False def writeImage(self, filename): """将下一个退出的帧写入图像文件""" self._imageFilename = filename def startWritingVideo(self, filename, encoding=cv2.VideoWriter_fourcc('I', '4', '2', '0')): self._videoFilename = filename self._videoEncoding = encoding def stopWritingVideo(self): """停止写入视频文件 """ self._videoFilename = None self._videoEncoding = None self._videoWriter = None def _writeVideoFrame(self): if not self.isWritingVideo: return if self._videoWriter is None: fps = self._capture.get(cv2.CAP_PROP_FPS) if fps == 0.0: # 捕获的FPS是未知的,所以使用估计值 if self._framesElapsed < 20: return else: fps = self._fpsEstimate size = (int(self._capture.get(cv2.CAP_PROP_FRAME_WIDTH)), int(self._capture.get(cv2.CAP_PROP_FRAME_HEIGHT))) self._videoWriter = cv2.VideoWriter( self._videoFilename, self._videoEncoding, fps, size) self._videoWriter.write(self._frame) class WindowManager(object): def __init__(self, windowName, keypresscallback=None): self.keypressCallback = keypresscallback self._windowName = windowName self._isWindowCreated = False @property def isWindowCreated(self): return self._isWindowCreated def createWindow(self): cv2.namedWindow(self._windowName) self._isWindowCreated = True def show(self, frame): cv2.imshow(self._windowName, frame) def destroyWindow(self): cv2.destroyWindow(self._windowName) self._isWindowCreated = False def processEvents(self): keycode = cv2.waitKey(1) if self.keypressCallback is not None and keycode != -1: keycode &= 0xFF self.keypressCallback(keycode)
filters.py
import cv2 import numpy import Opencv_test.utils def strokeEdges(src,dst,blurKsize = 7,edgeKsize = 5): if blurKsize >= 3: blurredSrc = cv2.medianBlur(src,blurKsize) graySrc = cv2.cvtColor(blurredSrc,cv2.COLOR_BGR2GRAY) else: graySrc = cv2.cvtColor(src, cv2.COLOR_BAYER_BG2BGR) cv2.Laplacian(graySrc, cv2.CV_8U, graySrc, ksize=edgeKsize) normalizedInverseAlpha = (1.0 / 255) * (255 - graySrc) channels = cv2.split(src) for channel in channels: channel[:] = channel * normalizedInverseAlpha cv2.merge(channels,dst) class BGRFuncFilter(object): def __init__(self, vFunc = None, bFunc = None, gFunc = None, rFunc = None,dtype = numpy.uint8) : length = numpy.iinfo(dtype).max + 1 self._bLookupArray = Opencv_test.utils.createLookupArray(Opencv_test.utils.createCompositeFunc(bFunc, vFunc), length) self._gLookupArray = Opencv_test.utils.createLookupArray(Opencv_test.utils.createCompositeFunc(gFunc, vFunc), length) self._rLookupArray = Opencv_test.utils.createLookupArray(Opencv_test.utils.createCompositeFunc(rFunc, vFunc), length) def apply(self, src, dst) : """Apply the filter with a BGR source/destination.""" b, g, r = cv2.split(src) Opencv_test.utils.applyLookupArray(self._bLookupArray, b, b) Opencv_test.utils.applyLookupArray(self._gLookupArray, g, g) Opencv_test.utils.applyLookupArray(self._rLookupArray, r, r) cv2.merge([ b, g, r ], dst) class BGRCurveFilter(BGRFuncFilter): def __init__(self, vPoints = None, bPoints = None,gPoints = None, rPoints = None, dtype = numpy.uint8): BGRFuncFilter.__init__(self, Opencv_test.utils.createCurveFunc(vPoints), Opencv_test.utils.createCurveFunc(bPoints), Opencv_test.utils.createCurveFunc(gPoints), Opencv_test.utils.createCurveFunc(rPoints), dtype) class BGRPortraCurveFilter(BGRCurveFilter): def __init__(self, dtype = numpy.uint8): BGRCurveFilter.__init__( self, vPoints = [ (0, 0), (23, 20), (157, 173), (255, 255) ], bPoints = [ (0, 0), (41, 46), (231, 228), (255, 255) ], gPoints = [ (0, 0), (52, 47), (189, 196), (255, 255) ], rPoints = [ (0, 0), (69, 69), (213, 218), (255, 255) ], dtype = dtype)
utils.py
import cv2,numpy,scipy.interpolate def createCurveFunc(points): """Return a function derived from control points.""" if points is None: return None num_points = len(points) if num_points < 2: return None xs, ys = zip(*points) if num_points < 4: kind = 'linear' # 'quadratic' is not implemented. else: kind = 'cubic' return scipy.interpolate.interp1d(xs, ys, kind,bounds_error = False) def createLookupArray(func, length = 256): """Return a lookup for whole-number inputs to a function. The lookup values are clamped to [0, length - 1].""" if func is None: return None lookup_array = numpy.empty(length) i = 0 while i < length: func_i = func(i) lookup_array[i] = min(max(0, func_i), length - 1) i += 1 return lookup_array def applyLookupArray(lookup_array, src, dst): """Map a source to a destination using a lookup.""" if lookup_array is None: return dst[:] = lookup_array[src] def createCompositeFunc(func0, func1): """Return a composite of two functions.""" if func0 is None: return func1 if func1 is None: return func0 return lambda x: func0(func1(x)) def createFlatView(array): """Return a 1D view of an array of any dimensionality.""" flat_view = array.view() flat_view.shape = array.size return flat_view
canny.py
import cv2 import numpy as np img = cv2.imread("F:\python\data\photos\screenshot1.png",0) cv2.imwrite("creenshot1canny.jpg",cv2.Canny(img,200,300)) cv2.imshow("mycanny",cv2.imread("creenshot1canny.jpg")) cv2.waitKey() cv2.destroyAllWindows()
备注:以上代码可实现调取摄像头,截图、录像等功能