Opencv

发布于:2025-04-12 ⋅ 阅读:(38) ⋅ 点赞:(0)

RGB三色: 

OpenCV是BGR存储图片,RGB 是大多数其他库(如 Matplotlib、PIL)的默认格式。

R(255,0,0)

G(0,255,0)

B(0,0,255)

import cv2
import numpy as np
import matplotlib.pyplot as plt

image = cv2.imread(r'C:\Users\hi\Desktop\2.png')

plt.figure(figsize=(20, 15))

plt.subplot(2, 2, 1)
plt.imshow(image[:,:,0], cmap='gray')
plt.title('blue')
plt.axis('off')

plt.subplot(2, 2, 2)
plt.imshow(image[:,:,1], cmap='gray')
plt.title('green')
plt.axis('off')

plt.subplot(2, 2, 3)
plt.imshow(image[:,:,2], cmap='gray')
plt.title('red')
plt.axis('off')

plt.subplot(2, 2, 4)
plt.imshow(image)
plt.title('original')
plt.axis('off')

plt.show()

---------------------------------------

 实际上的RGB转换成灰度图像是RGB三色的权重值:0.299*R+0.587*G+0.114*B

验证如下:(test是分离三通道,加权后用公式计算的)

import cv2
import numpy as np
import matplotlib.pyplot as plt

image = cv2.imread(r'C:\Users\hi\Desktop\2.png')
b,g,r = cv2.split(image)

gray_manual = 0.299*r+0.587*g+0.114*b;
gray_manual = np.uint8(gray_manual)

plt.figure(figsize=(15, 5))

# 灰度图
plt.subplot(1, 3, 1)
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
plt.imshow(gray,cmap='gray')
plt.title('gray')
plt.axis('off')

# 原图
plt.subplot(1, 3, 2)
plt.imshow(image)
plt.title('original')
plt.axis('off')
#测试
plt.subplot(1, 3, 3)
plt.imshow(gray_manual,cmap='gray')
plt.title('test')
plt.axis('off')

plt.show()

-------------------------------------------------------------------

crop裁剪:

裁剪区域判断可以看图像的属性去微调:

[200:500,400:800]指的是宽200到500,和长400到800这个区域。 

import cv2
import numpy as np
import matplotlib.pyplot as plt

image = cv2.imread(r'C:\Users\hi\Desktop\2.png')
image_crop = image[200:500,400:800]
plt.figure(figsize=(10, 5))

# 裁剪
plt.subplot(1, 2, 1)
plt.imshow(image_crop)
plt.title('crop')
plt.axis('off')

# 原图
plt.subplot(1, 2, 2)
plt.imshow(image)
plt.title('original')
plt.axis('off')

plt.show()

 ---------------------------------------------------------------

绘制功能:

import cv2
import numpy as np
import matplotlib.pyplot as plt

image = cv2.imread(r'C:\Users\hi\Desktop\2.png')
image_crop = image[200:500,450:750]


cv2.circle(image_crop,(150,150),30,(0,0,255),7)
cv2.putText(image_crop,"CV",(130,150),0,1,(0,0,0),2,1)
cv2.imshow("image",image_crop)
cv2.waitKey()

-------------------------------------------------------------------------------------

 滤波去噪:

快速模糊平滑 → 均值滤波

去噪+保留细节 → 高斯滤波

采用均值、高斯滤波去噪:均值和高斯滤波不改变图像尺寸

卷积核(滤波核)在图像上滑动,对每个像素点及其邻域进行加权计算。

  • 中心像素:卷积核覆盖区域的加权平均值会直接影响该像素的新值。
  • 边缘像素:当卷积核靠近图像边界时,邻域部分超出图像范围,此时需通过填充策略处理越界区域

比如:生成一张带了高斯噪声的图像,保存到本地

import cv2
import numpy as np
import matplotlib.pyplot as plt

# 读取图像(BGR格式)
img = cv2.imread(r'C:\Users\hi\Desktop\2.png')

# 生成高斯噪声
# 参数说明:
#   (1) 噪声矩阵形状与图像一致
#   (2) 均值 mean=0
#   (3) 标准差 sigma=25(根据需求调整)
noise = np.random.normal(loc=0, scale=55, size=img.shape).astype(np.float32)

# 将噪声叠加到图像上
noisy_img = img.astype(np.float32) + noise

# 限制像素值范围 [0, 255] 并转换为 uint8
noisy_img = np.clip(noisy_img, 0, 255).astype(np.uint8)
cv2.imwrite(r'C:\Users\hi\Desktop\6.png',noisy_img)

 滤波处理:

    import cv2
    import matplotlib.pyplot as plt
    
    # 读取图像
    img = cv2.imread(r'C:\Users\hi\Desktop\6.png')
    
    # 均值滤波
    blur_mean = cv2.blur(img, (5, 5))
    
    # 高斯滤波
    blur_gaussian = cv2.GaussianBlur(img, (7, 7), sigmaX=0)
    
    cv2.imwrite(r'C:\Users\hi\Desktop\7.png',blur_gaussian)
    
    # 显示结果
    plt.figure(figsize=(18, 9))
    #plt.subplot(121), plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)), plt.title("Original")
    plt.subplot(121), plt.imshow(cv2.cvtColor(blur_mean, cv2.COLOR_BGR2RGB)), plt.title("Mean Filter")
    plt.subplot(122), plt.imshow(cv2.cvtColor(blur_gaussian, cv2.COLOR_BGR2RGB)), plt.title("Gaussian Filter")
    plt.show()
    

    -------------------------------------------------------------------------------------

    特征提取:提取图像的转角,然后用圆圈标记出来(500是最大数量,0.05是阈值,调节阈值筛选想要的转角)

    import cv2
    import numpy as np
    import matplotlib.pyplot as plt
    
    image = cv2.imread(r'C:\Users\hi\Desktop\2.png')
    
    gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
    
    corners = cv2.goodFeaturesToTrack(gray,500,0.05,10)
    
    for corner in corners:
        x,y = corner.ravel()
        cv2.circle(image,(int(x),int(y)),3,(255,0,255),-1)
    
    cv2.imshow("corners",image)
    cv2.waitKey()
    

    -------------------------------------------------------------------------------- 

    模板匹配:

    图像是用画图工具自己做的。

    visionpro的模板匹配更加准确一些。

    import cv2
    import numpy as np
    import matplotlib.pyplot as plt
    
    image = cv2.imread(r'C:\Users\hi\Desktop\3.png')
    gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
    
    template = gray[110:190,20:130]
    num = 0
    #cv2.rectangle(image,(110,20),(190,120),(0,255,0),2)
    
    match = cv2.matchTemplate(gray,template,cv2.TM_CCOEFF_NORMED)
    locations = np.where(match >= 0.9)#0.9为阈值
    
    h,w = template.shape[0:2]
    for p in zip(*locations[::-1]):
        x1,y1 = p[0],p[1]
        x2,y2 = x1+w,y1+h
        cv2.rectangle(image,(x1,y1),(x2,y2),(0,255,0),1)
        num+=1
    
    cv2.putText(image,"nums:"+str(num),(10,50),0,1,(0,0,0),1,1)
    cv2.imshow("image",image)
    cv2.waitKey() 
    

    ---------------------------------------------------------------------------- 

    边缘检测:

    一阶导数在灰度突变处(如边缘)会呈现较大的值。

    ​梯度方向:梯度向量 ∇f=(∂x/∂f​,∂y/∂f​) 的方向指向亮度变化最快的方向。

    图像梯度算法:边缘通常是灰度值变化剧烈的区域,梯度算法可以用来提取边缘

    一阶看的是变化率,提取的是粗略的边缘,使用算子有Sobel.

    二阶看的是变化的加速度,提取的是精确的边缘,但是非常容易受到噪声影响,有噪声就需要对噪声进行处理,使用算子有Canny(分段函数式取值,有过渡区间)和Laplacian(直接粗暴,没有过渡区间),Canny更加抗噪声。

    Sobel和Canny对比如下:

    import cv2
    import numpy as np
    import matplotlib.pyplot as plt
    
    # 读取图像
    image = cv2.imread(r'C:\Users\12581\Desktop\color_flowers.bmp', cv2.IMREAD_GRAYSCALE)
    
    # 应用Canny边缘检测
    # 参数1: 最小阈值,参数2: 最大阈值
    edges = cv2.Canny(image, 100, 200)
    
    # 显示原图和边缘检测结果
    plt.figure(figsize=(10, 5))
    
    # 原图
    plt.subplot(1, 2, 1)
    plt.imshow(image, cmap='gray')
    plt.title('Original Image')
    plt.axis('off')
    
    # 边缘图
    plt.subplot(1, 2, 2)
    plt.imshow(edges, cmap='gray')
    plt.title('Canny Edge Detection')
    plt.axis('off')
    
    plt.show()

    Sobel:边缘非常粗糙

    import cv2
    import numpy as np
    import matplotlib.pyplot as plt
    
    # 读取图像
    image = cv2.imread(r'C:\Users\12581\Desktop\color_flowers.bmp', cv2.IMREAD_GRAYSCALE)
    
    # 应用Canny边缘检测
    # 参数1: 最小阈值,参数2: 最大阈值
    edges = cv2.Canny(image, 100, 200)
    
    # 显示原图和边缘检测结果
    plt.figure(figsize=(10, 5))
    
    # 原图
    plt.subplot(1, 2, 1)
    plt.imshow(image, cmap='gray')
    plt.title('Original Image')
    plt.axis('off')
    
    # 边缘图
    plt.subplot(1, 2, 2)
    plt.imshow(edges, cmap='gray')
    plt.title('Canny Edge Detection')
    plt.axis('off')
    
    plt.show()
    

    Canny: 边缘准确

    ----------------------------------------------------------------------------

    二值化:

    (0-255)灰度图像变成(0-1)二值图像

    OpenCV对比与Visionpro还是有强大的地方的,它的二值化可以分区域来设置不同的阈值。

    比如这张图片,明暗分布不均匀:

    Visionpro效果:

     OpenCV:

    import cv2
    import numpy as np
    import matplotlib.pyplot as plt
    
    gray = cv2.imread(r'C:\Users\hi\Desktop\4.jpg',cv2.IMREAD_GRAYSCALE)
    ret,binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
    binary_adaptive = cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,151,7)
    cv2.imshow("image1",binary)
    cv2.imshow("image2",binary_adaptive)
    
    cv2.waitKey() 
    

     OTSU阈值算法:也叫大津法(专门用在cv2.threshold(),不需要调整参数,适合场景是光照均匀的图片,不适合在光照不均匀和噪声多的图片)

    我们看一下OTSU的强大性:

    import cv2
    import numpy as np
    import matplotlib.pyplot as plt
    
    gray = cv2.imread(r'C:\Users\hi\Desktop\2.png',cv2.IMREAD_GRAYSCALE)
    ret,binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
    #binary_adaptive = cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,151,7)
    ret,binary_otsu = cv2.threshold(gray,0,255,cv2.THRESH_BINARY|cv2.THRESH_OTSU)
    plt.figure(figsize=(20, 15))
    
    plt.subplot(2, 2, 1)
    plt.imshow(gray, cmap='gray')
    plt.title('gray')
    plt.axis('off')
    
    plt.subplot(2, 2, 2)
    plt.imshow(binary, cmap='gray')
    plt.title('binary')
    plt.axis('off')
    
    plt.subplot(2, 2, 3)
    plt.imshow(binary_otsu, cmap='gray')
    plt.title('binary_otsu')
    plt.axis('off')
    
    plt.show()
    

     原图是gray,不用otsu就需要人工去调阈值,binary这张图还需要去调整参数。

    -----------------------------------------------

    形态学

    膨胀(dilated)、腐蚀(eroded)、开运算(先腐蚀后膨胀)、闭运算(先膨胀后腐蚀)

    import cv2
    import numpy as np
    import matplotlib.pyplot as plt
    
    image = cv2.imread(r'C:\Users\hi\Desktop\2.png',cv2.IMREAD_GRAYSCALE)
    ret,gray = cv2.threshold(image,200,255,cv2.THRESH_BINARY_INV|cv2.THRESH_OTSU)
    kernel = np.ones((7,7),np.uint8)
    dilated = cv2.dilate(gray,kernel,iterations=1)#膨胀
    eroded = cv2.erode(gray,kernel,iterations=1)#腐蚀
    open = cv2.dilate(eroded,kernel,iterations=1)#开运算
    close = cv2.erode(dilated,kernel,iterations=1)#闭运算
    
    plt.figure(figsize=(20, 15))
    
    plt.subplot(2, 2, 1)
    plt.imshow(dilated , cmap='gray')
    plt.title('dilated ')
    plt.axis('off')
    
    plt.subplot(2, 2, 2)
    plt.imshow(eroded, cmap='gray')
    plt.title('eroded')
    plt.axis('off')
    
    plt.subplot(2, 2, 3)
    plt.imshow(open, cmap='gray')
    plt.title('open')
    plt.axis('off')
    
    plt.subplot(2, 2, 4)
    plt.imshow(close, cmap='gray')
    plt.title('close')
    plt.axis('off')
    
    plt.show()
    
    
    
    
    

     开运算和闭运算,膨胀和腐蚀,哪个先使用,哪个的效果就是主要效果。如图就是,闭运算是膨胀先使用,就算使用了腐蚀有效恢复了图像形态,但是膨胀效果还是主要效果。

    ---------------------------------------------------------------------

    读取相机流:

    import cv2
    
    capture = cv2.VideoCapture(0)
    
    while True:
        ret,frame = capture.read()
        cv2.imshow("camera",frame)
        key = cv2.waitKey(1)
        if key!=-1:
            break
    capture.release()


    网站公告

    今日签到

    点亮在社区的每一天
    去签到