计算机视觉基础系列(python与opencv的操作与运用/tensorflow的基础介绍)(十三)---图像的融合和边缘检测

博客主要介绍了图像融合和边缘检测相关知识。图像融合方面,讲解了直接加法运算及线性融合,对比了OpenCV和Numpy加法运算差异;边缘检测部分,阐述了OpenCV - Python中Canny()参数步骤,还介绍了利用Sobel算子进行边缘检测的原理和代码实现。

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

1 图像融合

被叠加的两张图片的大小、类型(高度/宽度/通道数)必须相同。 但是如果这两张图片大小不相同,有什么方法解决?具体解决方法请点击此处查看

1.1 cv2.add(img1,img2):直接对两张图片作加法运算

Numpy中可以直接用res = img1 + img2相加,但这两者的结果并不相同,因为OpenCV中的加法运算是饱和运算(就是当运算结果大于一个上限或小于一个下限时,结果就等于上限或是下限。),而Numpy中的加法运算是取模运算。

如下面代码中cv2.add(x,y)运行结果为[[255]],是因为250+10 = 260 >= 255,所以结果就等于上限255,x+y运行结果为[4],是因为250+10 = 260 mod 255 = 4。

from imutils import *
import os 
os.chdir('D:/BaiduYunDownload/')

img1 = imread('image1.jpg')
img2 = imread('image2.jpg')
show(img1)
show(img2)

x = np.uint8([250])
y = np.uint8([10])
print(cv2.add(x,y)) #运行结果为[[255]]
print(x+y) #运行结果为[4]

res = img1 + img2
show(res)#显示使用数组加法后的图片
add = cv2.add(img1,img2)
show(add)#显示使用OpenCV中add函数的图片

想了解上面代码中的from imutils import *点击此处

1.2  cv2.addWeighted(src1, alpha, src2, beta, gamma[, dst[, dtype]]):也是一种图片相加的操作,可以实现两张图片的线性融合。

将沙漠和老虎的图片融合,沙漠的权重为0.6,老虎的权重为0.4

from imutils import *
import os 
os.chdir('C:/Users/lenovo/Pictures/')

img1 = imread('desert.jpg')
img2 = imread('tiger.jpg')
dst = cv2.addWeighted(img1,0.6,img2,0.4,0)#γ的取值为0
show(dst)

运行结果为:

如果想不断调节alpha的值,查看不同情况下的融合图像。(可以增加一个滑动条)

import cv2
import numpy as np
import os 
os.chdir('C:/Users/lenovo/Pictures/')

img1 = cv2.imread('desert.jpg')
img2 = cv2.imread('tiger.jpg')
cv2.namedWindow('addImage')

#回调函数
def nothing(x):
    pass

#添加一个调节alpha值得滑动条
alpha = 0 #初始化
cv2.createTrackbar('alpha','addImage',0,10,nothing)

while(1):
    cv2.imshow('addImage',dst)
    k = cv2.waitKey(1) & 0xFF
    if k == ord('q'): #按q键退出
        break
    #获得滑动条的value值
    alpha = cv2.getTrackbarPos('alpha','addImage')
    alpha = alpha/10
    beta = 1.0 - alpha
    dst = cv2.addWeighted(img1,alpha,img2,beta,0)#γ的取值为0

cv2.destroyAllWindows()

2 图像的边缘检测

2.1 OpenCV-Python 中 Canny() 参数

步骤:

  • 彩色图像转换为灰度图像(以灰度图或者单通道图读入)
  • 对图像进行高斯模糊(去噪)
  • 计算图像梯度,根据梯度计算图像边缘幅值与角度
  • 沿梯度方向进行非极大值抑制(边缘细化)
  • 双阈值边缘连接处理
  • 二值化图像输出结果
  • """
    cv2.Canny(image,            # 输入原图(必须为单通道图)
              threshold1, 
              threshold2,       # 较大的阈值2用于检测图像中明显的边缘
              [, edges[, 
              apertureSize[,    # apertureSize:Sobel算子的大小
              L2gradient ]]])   # 参数(布尔值):
                                  true: 使用更精确的L2范数进行计算(即两个方向的倒数的平方和再开放),
                                  false:使用L1范数(直接将两个方向导数的绝对值相加)。
    """
    
    import cv2
    import numpy as np  
     
    original_img = cv2.imread("qingwen.png", 0)
    
    # canny(): 边缘检测
    img1 = cv2.GaussianBlur(original_img,(3,3),0)
    canny = cv2.Canny(img1, 50, 150)
    
    # 形态学:边缘检测
    _,Thr_img = cv2.threshold(original_img,210,255,cv2.THRESH_BINARY)#设定红色通道阈值210(阈值影响梯度运算效果)
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))         #定义矩形结构元素
    gradient = cv2.morphologyEx(Thr_img, cv2.MORPH_GRADIENT, kernel) #梯度
    
    cv2.imshow("original_img", original_img) 
    cv2.imshow("gradient", gradient) 
    cv2.imshow('Canny', canny)
    
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

    2.2 利用sobel算子进行源码的边缘检测

索贝尔算子(Sobel operator)主要用作边缘检测,在技术上,它是一离散性差分算子,用来运算图像亮度函数的灰度之近似值。在图像的任何一点使用此算子,将会产生对应的灰度矢量或是其法矢量。

Sobel卷积因子为:

该算子包含两组3x3的矩阵,分别为横向及纵向,将之与图像作平面卷积,即可分别得出横向及纵向的亮度差分近似值。如果以A代表原始图像,Gx及Gy分别代表经横向及纵向边缘检测的图像灰度值,其公式如下:

 

具体计算如下:

其中f(a,b), 表示图像(a,b)点的灰度值;图像的每一个像素的横向及纵向灰度值通过以下公式结合,来计算该点灰度的大小:

 通常,为了提高效率,使用不开平方的近似值:

 如果梯度G大于某一阀值 则认为该点(x,y)为边缘点,然后可用以下公式计算梯度方向:

Sobel算子根据像素点上下、左右邻点灰度加权差,在边缘处达到极值这一现象检测边缘。对噪声具有平滑作用,提供较为精确的边缘方向信息,边缘定位精度不够高。当对精度要求不是很高时,是一种较为常用的边缘检测方法。 

实现的代码如下:

import cv2
import numpy as np

import math
img = cv2.imread('1.jpg', 1)
info = img.shape
cv2.imshow('src', img)
height = info[0]
width = info[1]
# sobel  1.算子模板  2.图片卷积   3.阈值判决
# 2.[1 2 3 4][a b c d]   a*1+b*2+c*3+d*4  =  dst
# sqrt(a*a+b*b) = f>th
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
dst = np.zeros((height, width, 1), np.uint8)
for i in range(0, height-2):
    for j in range(0, width-2):
        gy = gray[i, j]*1 + gray[i, j+1]*2 + gray[i, j+2]*1 - gray[i+2, j]*1 - gray[i+2, j+1]*2 - gray[i+2, j+2]*1
        gx = gray[i, j] + gray[i+1, j]*2 + gray[i+2, j] - gray[i, j+2] - gray[i+1, j+2]*2 - gray[i+2, j+2]*1
        grad = math.sqrt(gx*gx+gy*gy)
        if grad > 50:
            dst[i, j] = 255
        else:
            dst[i, j] = 0
cv2.imshow('dst', dst)
cv2.waitKey(0)

最后的实验效果是:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值