python中opencv读取图片的小知识点

前言

之前一直会搞混opencv读取图片的时候到底是(height, width, channel) 还是(width, height, channel),以及设置像素点的时候的(x,y)位置。所以在这里记录一下各种小知识点,以后忘记的时候可以翻阅一下。

小知识点

  1. 图像的数据结构
    当用img = cv2.imread('pic.png')的时候:
    img.shape返回的是: (height, width, channel)
    下面是以BGR格式为例介绍Image的数据结构.
    在这里插入图片描述
    第一维度 : Height 高度, 对应这张图片的 nRow行数

    第二维度 : Width 宽度, 对应这张图片的nCol 列数

    第三维度: Value BGR三通道的值.

  2. 图像切割与ROI

    • SelectROI函数
      rect = cv2.selectROI("image", img, showCrosshair, fromCenter)

      参数解释

      “image” : winName 窗口名称

      img : 目标想要裁剪的图像

      showCrosshair : 是否显示网格

      True 显示网格

      False 只有矩形

      fromCenter:

      True 第一次选中的点为矩形的中心.

      False 第一次选中的点为矩形的左上角.

      返回的是一个tuple值, 代表矩形区域. 分别代表矩形左上角坐标 (x, y) 与矩形宽度w跟高度h
      (x, y, w, h) = rect
      切片的时候一定要注意, 第一维指的是行数, 第二维度指的是列数.
      imCrop = img[y : y+h, x:x+w]

  3. 浅拷贝和深拷贝
    图像拷贝有两种概念

    1. 浅拷贝
      当图像之间进行赋值时,图像数据并未发生复制,两个对象指向同一块内存,改变图像2会影响图像1
      cv::Mat img;
      img = image;
      
    2. 深拷贝
      当图像之间进行赋值时,图像数据发生复制,两个对象指向不同的内存,改变图像2不会影响图像1。
      因为cv传入图片都是用numpy存的,对于numpy,有函数np.copy(A)
      import numpy as np
      A = np.arange(10)
      B = np.copy(A)
      # 这样就是深拷贝啦
      
  4. np中的reshape和resize的区别

    1. np.reshapeA.reshape
      • reshape函数变形前与变形后的size必须相同.
      • A.reshape((2,3))并没有改变A的形状,改变形状的对象以返回值的形式。
    2. np.resizeA.resize
      • 不要求新的array的size 必须与原来array的size相同, 可以自动填充
      • A.resize((2,3))改变了A,不返回值!
  5. np.random随机函数模块

    1. np.random.rand
      很明显,这个是生成0-1的随机数
    2. np.random.randn
      这个最后的n出卖了你,就是Normalization,正态分布。生成正态分布啊,那肯定就不是0-1啊!

    值得注意的是:

    numpy.random.rand(d0, d1, ..., dn)
    numpy.random.randn(d0, d1, ..., dn)
    

    这两个东西的构造函数都是一样的,就是传入不用tuple,直接维度就OK了。

  6. 滑动条
    之前一直都搞不懂滑动条里的回调函数,今天有点清楚了。
    cv2.createTrackbar(trackbar_name,window_name,min_value,max_value,callback_func)
    依次传入的函数

    • trackbar_name 滑条的名称,获取这个滑条的数值也是通过名称
    • window_name 滑条所在窗口 (window) 的名称
    • min_value 滑条最小值
    • max_value 滑条最大值
    • callback_func 回调函数,这个参数其实类似C语言中的函数指针,我传入的是函数名称,每次滑条被拖动的时候,都会执行这个函数.

    例子:

    # 这个nothing的意思就是啥也不做。
    def nothing(x):
        print(x)
    cv2.createTrackbar('gray_value','image',0,255,nothing)
    

    这里的nothing(x),被传入的实际是滑条的当前取值。也就是说,createTrackbar这个函数,会将当前的滑动条位置传给回调函数!!!

  7. cv2.waitKey()
    原型:cv2.waitKey([delay]) → retval

    • 有按键按下的时候
      返回值为当前键盘按键值;
    • 没有按键按下的时候:
      如果delay>0,那么超过指定时间则返回-1;如果delay=0,将没有返回值
  8. 用鼠标回调函数、滑动条回调函数来创建一个彩色绘图板(要熟悉以下代码)

    
    '''
    鼠标按下绘制线条,可以调整线条粗细,变换颜色,线条也更流畅(怎么做到的)
    '''
    import cv2 
    import numpy as np 
    
    isMouseLBDown = False
    circleColor = (0,0,0)
    circleRadius = 5 #画笔的粗细
    lastPoint = (0, 0) # 获取最后的点有什么用
    
    def draw_circle(event, x, y, flags, param):
        global img 
        global isMouseLBDown
        global circleColor
        global lastPoint
    
        if event == cv2.EVENT_LBUTTONDOWN:
            isMouseLBDown = True
            cv2.circle(img, (x,y), int(circleRadius/2), circleColor, -1)
            # 这里要加lastPoint
            lastPoint = (x,y)
        elif event == cv2.EVENT_LBUTTONUP:
            isMouseLBDown = False 
        elif event == cv2.EVENT_MOUSEMOVE:
            if isMouseLBDown:
                # 这里是line
                cv2.line(img, pt1=lastPoint, pt2=(x,y), color=circleColor, thickness=circleRadius)
                lastPoint = (x, y)
    
    # 更新颜色
    def updateCircleColor(x):
        global circleColor
        global colorPreviewImg  # 预览颜色
    
        r = cv2.getTrackbarPos('Channel_Red', 'image')
        g = cv2.getTrackbarPos('Channel_Green', 'image')
        b = cv2.getTrackbarPos('Channel_Blue', 'image')
    
        circleColor = (b, g, r)
        colorPreviewImg[:] = circleColor
    
    # 更新画笔的宽度
    def updateCircleRadius(x):
        global circleRadius 
        global radiusPreview
    
        circleRadius = cv2.getTrackbarPos('Circle_Radius', 'image')
        # 重置画布
        radiusPreview[:] = (255, 255, 255)
        cv2.circle(radiusPreview, center=(50,50), radius=int(circleRadius/2), color=(0,0,0), thickness=-1)
    
    
    
    # 主体
    img = np.zeros((512, 512, 3), dtype=np.uint8)
    # 图片设置为白色
    img[:] = (255, 255, 255)
    
    # 用于预览画笔的颜色
    colorPreviewImg = np.ones((100, 100, 3), np.uint8)
    colorPreviewImg[:] = (0, 0, 0)
    # 用于预览画笔的粗细
    radiusPreview = np.ones((100, 100, 3), np.uint8)
    radiusPreview[:] = (255, 255, 255)
    
    cv2.namedWindow('image')
    cv2.namedWindow('colorPreview')
    cv2.namedWindow('radiusPreview')
    
    cv2.createTrackbar('Channel_Red', 'image', 0, 255, updateCircleColor)
    cv2.createTrackbar('Channel_Green', 'image', 0, 255, updateCircleColor)
    cv2.createTrackbar('Channel_Blue', 'image', 0, 255, updateCircleColor)
    
    cv2.createTrackbar('Circle_Radius', 'image', 1, 20, updateCircleRadius)
    
    cv2.setMouseCallback('image', draw_circle)
    
    while True:
        cv2.imshow('colorPreview', colorPreviewImg)
        cv2.imshow('radiusPreview', radiusPreview)
        cv2.imshow('image', img)
        if cv2.waitKey(1) == ord('q'):
            break 
    
    
    cv2.destroyAllWindows()
    cv2.imwrite('MousePaint04.png', img)
    
  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

zedjay_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值