OpenCV机器视觉-图片操作原理(二)

图像特效


## 图像融合 图像融合,即按照一定的比例将俩张图片融合在一起。

执行这样的融合需要用到opencv提供的如下api:

cv.addWeighted(图像1,权重1,图像2,权重2,叠加之后的像素偏移值)
注意:
    进行叠加的两张图片宽高应该相同
    叠加之后的像素偏移值如果填的话不要填太大,超过255会导致图像偏白

示例代码:

import cv2

itheima = cv2.imread("./img/qq.png", cv2.IMREAD_COLOR)
cv2.imshow("itheima", itheima)

tony = cv2.imread("./img/pp.png", cv2.IMREAD_COLOR)
cv2.imshow("tony", tony)

# 进行叠加时的插值
dst = cv2.addWeighted(itheima, 0.5, tony, 0.5, 0)
cv2.imshow("dst", dst)

cv2.waitKey(0)
cv2.destroyAllWindows()

灰度处理


一张彩色图片通常是由BGR三个通道叠加而成,为了便于图像特征识别,我们通常会将一张彩色图片转成灰度图片来进行分析,当我们转成灰色图片之后,图片中边缘,轮廓特征仍然是能够清晰看到的,况且在这种情况下我们仅需要对单一通道进行分析,会简化很多操作。

示例代码:

import cv2

# 方式一:直接以灰度图像的形式读取
img = cv2.imread('./timg.jpg', cv2.IMREAD_GRAYSCALE)
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

# 方式二:以彩图的方式读取
img = cv2.imread('./timg.jpg', cv2.IMREAD_COLOR)
# 将原图的所有颜色转换成灰色
dstImg = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imshow('dstImg', dstImg)
cv2.waitKey(0)
cv2.destroyAllWindows()

原理演示


方式一: gray = (B+G+R)/3
import numpy as np
from cv2 import cv2

img = cv2.imread("./timg.jpg", cv2.IMREAD_COLOR)

# 获取图片宽高信息
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]

# 定义一个与原图同样大小的矩阵
dstImg = np.zeros(imgInfo, np.uint8)

# 遍历dstImg,填充数据
for row in range(height):
    for col in range(width):
        # 获取原来的像素值
        (b, g, r) = img[row, col]
        # 计算灰度
        gray = np.uint8((int(b) + int(g) + int(r)) / 3)
        print(gray)
        # 向目标矩阵中填值
        dstImg[row, col] = gray

cv2.imshow("dstimg", dstImg)
cv2.waitKey(0)

方式二: 利用著名的彩色转灰色心理学公式: Gray = R*0.299 + G*0.587 + B*0.114

import cv2 as cv
import numpy as np

# 将图片数据读取进来
img = cv.imread("img/itheima.jpg",cv.IMREAD_COLOR)

# 获取图片宽高信息
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]

# 定义一个与原图同样大小的矩阵
dstImg = np.zeros(imgInfo,np.uint8)

# 遍历dstImg,填充数据
for row in range(height):
    for col in range(width):
        # 获取原来的像素值
        (b,g,r) = img[row,col]
        # 计算灰度
        # gray = np.uint8((int(b)+int(g)+int(r))/3)
        # 采用心理学公式计算
        gray = b*0.114 + g*0.587 + r*0.299
        # 向目标矩阵中填值
        dstImg[row,col]=gray

cv.imshow("dstimg",dstImg)
cv.waitKey(0)

颜色反转


灰度反转


例如在一张灰度图片中,某个像素点的灰度值为100, 然后我们进行颜色反转之后,灰度值变为255-100 = 155 , 从下图我们可以看出,进行颜色反转之后,整张图片看起来非常像我们小时候所看到的胶卷底片!
在这里插入图片描述

import cv2 as cv
import numpy as np

# 将图片数据读取进来
img = cv.imread("./timg.jpg", cv.IMREAD_GRAYSCALE)
cv.imshow("img", img)
# 获取原图信息
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]

# 创建一个和原图同样大小的矩阵
dstImg = np.zeros((height, width, 1), np.uint8)

for row in range(height):
    for col in range(width):
        # 获取原图中的灰度值
        gray = img[row, col]
        # 反转
        newColor = 255 - gray
        # 填充
        dstImg[row, col] = newColor

cv.imshow("dstimg", dstImg)
cv.waitKey(0)

彩图反转


相对于灰度图片,彩色图片其实只是由3个灰度图片叠加而成,如果彩色图片进行颜色反转,我们其实只需要让每个通道的灰度值进行反转即可。

在这里插入图片描述

import cv2
import numpy as np

img = cv2.imread('./timg.jpg', cv2.IMREAD_COLOR)
cv2.imshow('img', img)
# 获取原图信息
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]

# 创建一个和原图同样大小的矩阵
dstImg = np.zeros((height, width, 3), np.uint8)

for row in range(height):
    for col in range(width):
        (b, g, r) = img[row, col]
        # 反转
        new_b = 255 - b
        new_g = 255 - g
        new_r = 255 - r
        # 填充
        dstImg[row, col] = (new_b, new_g, new_r)

cv2.imshow('dstImg', dstImg)
cv2.waitKey(0)
cv2.destroyAllWindows()

马赛克效果


马赛克指现行广为使用的一种图像(视频)处理手段,此手段将影像特定区域的色阶细节劣化并造成色块打乱的效果,因为这种模糊看上去有一个个的小格子组成,便形象的称这种画面为马赛克。其目的通常是使之无法辨认。

下面,我们来介绍一下实现马赛克的思路!

假设我们将要打马赛克的区域按照4x4进行划分,我们就会得到如下左图的样子!

接下来我们要干的就是让这个4x4块内的所有像素点的颜色值都和第一个像素点的值一样.

经过运算之后,我们整个4x4块内的所有像素点就都成了黄色! 从而掩盖掉了原来的像素内容!
在这里插入图片描述
在这里插入图片描述

import cv2

img = cv2.imread('./timg.jpg', cv2.IMREAD_COLOR)
cv2.imshow('img', img)
# 获取原图信息
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]

# 遍历要打马赛克的区域 宽度430 高度220
for row in range(160, 240):
    for col in range(100, 200):
        # 每10*10的区域像素点改变成一样的颜色
        if row % 10 == 0 and col % 10 == 0:
            # 获取当前的颜色
            (b, g, r) = img[row, col]
            # 改变一致颜色
            for i in range(10):
                for j in range(10):
                    img[row + i, col + j] = (b, g, r)

cv2.imshow('dstimg', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

毛玻璃效果


毛玻璃的效果和前面讲过的马赛克效果其实是非常相似的, 只不过毛玻璃效果是从附近的颜色块中,随机的去选择一个颜色值作为当前像素点的值!

我们还是以4x4的块大小为例,当我们去遍历每个像素点的时候, 当前像素点的颜色值,我们随机从它附近4x4的区域内选择一个颜色值作为当前像素点的值!

在这里插入图片描述
在这里插入图片描述

import random

import cv2
import numpy as np

img = cv2.imread('./timg.jpg', cv2.IMREAD_COLOR)
cv2.imshow('img', img)
# 获取原图信息
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]

# 创建一个和原图同样大小的空白矩阵
dstImg = np.zeros((height, width, 3), np.uint8)

# 定义偏移量,表示从后面6个像素中随机选取一个颜色值
offset = 6

# 向空白矩阵填入颜色值
for row in range(height):
    for col in range(width):
        # 计算随机数
        index = int(random.random() * offset)
        # 计算随机行号
        randomRow = row + index if row + index < height else height - 1
        # 计算随机列号
        randomCol = col + index if col + index < width else width - 1
        # 选择附近的一个像素点颜色
        (b, g, r) = img[randomRow, randomCol]
        # 填充到空白矩阵中
        dstImg[row, col] = (b, g, r)

cv2.imshow('dstimg', dstImg)
cv2.waitKey(0)
cv2.destroyAllWindows()

图片浮雕效果


梯度


前面做过一个毛玻璃效果的图片, 其实原理很简单对吧,我们只需要让当前像素点的颜色和附近像素点的颜色一致就可以了! 这样带来的效果其实是图片变得模糊.

那么模糊图片和清晰图片之间的差异是什么呢? 从视觉角度来讲, 图像模糊是因为图像中物体的边缘轮廓不明显,就好比一个近视的同学,摘下眼镜看东西,整个世界的轮廓都是模糊的. 再进一步理解就是物体边缘灰度变化不强烈,层次感不强造成的! 那么反过来, 如果物体轮廓边缘灰度变化明显些, 层次感强些图像不就是清晰一些了吗?

这种灰度变化明不明显强不强烈该如何定义呢 ? 我们学过微积分, 微分就是求函数的变化率,即导数(梯度). 其实梯度我们可以把它理解为颜色变化的强度, 更直白一点说梯度相当于是2个相邻像素之间的差值!
在这里插入图片描述
我们先看第一行数据, 在X轴方向上,颜色值都为100,我们并没有看到任何的边缘

但是在Y轴方向上, 我们可以看到100和50之间有明显的边缘,其实这个就是梯度

浮雕效果相信大家都有比较熟悉,在opencv中我们想要实现浮雕效果,只需套用如下公式即可:

gray = gray0-gray1+120

其中,相邻像素值之差可以体现边缘的突变或者称为梯度

末尾加上120只是为了增加像素值的灰度.

当然,在这个运算的过程中,我们还需要注意计算结果有可能小于0或者大于255
在这里插入图片描述

import cv2
import numpy as np

img = cv2.imread('./timg.jpg', cv2.IMREAD_COLOR)
cv2.imshow('img', img)

imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]

# 将图片转换成灰度图片
grayImg = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 创建一张与原图相同大小的空白矩阵
dstImg = np.zeros((height, width, 1), np.uint8)

# 向空白图片中填充内容
for row in range(height):
    for col in range(width - 1):
        # 获取当前像素值
        gray0 = grayImg[row, col]
        # 获取相邻的一个像素点灰度
        gray1 = grayImg[row, col + 1]
        # 计算新的灰度值
        gray = int(gray0) - int(gray1) + 120
        # 校验gray是否越界
        gray = gray if gray < 255 else 255
        gray = gray if gray > 0 else 0
        # 将值填充到空白的矩阵当中
        dstImg[row, col] = gray

cv2.imshow('dstimg', dstImg)
cv2.waitKey(0)
cv2.destroyAllWindows()

绘制图形


前面的所有操作,其实都是在原图的基础上进行修改! 现在假设我们想在原图上绘制一些标记或者轮廓,那么我们就需要来学习一下opencv给我们提供的相应API,在这些API中,常见的有绘制直线,绘制圆,绘制矩形。

# 绘制线段 参数2:起始点 参数3:结束点 参数4:颜色 参数5:线条宽度
cv.line(图片矩阵,起始点,结束点,颜色值,线条的宽度,线条的类型)
# 绘制一个矩形 参数2: 左上角  参数3:右下角 参数4:颜色  参数5:线条宽度,若为负数,则填充整个矩形
cv.rectangle(dstImg,(250,90),(470,180),(0,255,0),-1)
# 绘制圆形 参数2:圆心  参数3:半径  参数4:颜色 参数5:线条宽度
cv.circle(dstImg,(450,280),90,(0,0,255),5)

在这里插入图片描述

import cv2 as cv
import numpy as np
import random

# 创建一个空白的矩阵
dstImg = np.zeros((400, 600, 3), np.uint8)

# 绘制线段 参数2:起始点 参数3:结束点 参数4:颜色 参数5:线条宽度
cv.line(dstImg, (50, 10), (400, 10), (255, 255, 0), 10)
# 扛锯齿
cv.line(dstImg, (50, 50), (400, 50), (255, 0, 0), 10, cv.LINE_AA)

# 绘制一个三角形
cv.line(dstImg, (50, 350), (150, 200), (255, 0, 0), 10)
cv.line(dstImg, (150, 200), (300, 350), (0, 255, 0), 10)
cv.line(dstImg, (300, 350), (50, 350), (0, 0, 255), 10)

# 绘制一个矩形 参数2: 左上角  参数3:右下角 参数4:颜色  参数5:线条宽度,若为负数,则填充整个矩形
cv.rectangle(dstImg, (250, 90), (470, 180), (0, 255, 0), -1)

# 绘制圆形 参数2:圆心  参数3:半径  参数4:颜色 参数5:线条宽度
cv.circle(dstImg, (450, 280), 90, (0, 0, 255), 5)

# 显示图片
cv.imshow("dstimg", dstImg)
cv.waitKey(0)

文字图片绘制


在图片上绘制文本,我们需要用到

# 绘制文字
font = cv.FONT_HERSHEY_SIMPLEX
# 参数2:文本 参数3:显示位置  参数4:字体 参数5:大小 参数6:颜色 参数7:粗细 参数8:线条类型
cv.putText(img,'www.itheima.com',(395,138),font,1,(0,0,255),2,cv.LINE_AA)

示例代码

import cv2

# 将图片数据读取进来
img = cv2.imread("./timg.jpg", cv2.IMREAD_COLOR)
cv2.imshow("img", img)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]

# 在图片上绘制矩形
cv2.rectangle(img, (210, 150), (220, 236), (0, 255, 0), 5)

# 绘制图片
lenaImg = cv2.imread("./timg.jpg", cv2.IMREAD_COLOR)
# 获取图片信息
imgInfo = lenaImg.shape
# 计算缩放图片宽高
scale = 0.3
height = int(imgInfo[0] * scale)
width = int(imgInfo[1] * scale)
# 缩放图片
newLenaImg = cv2.resize(lenaImg, (height, width))
# 遍历
for row in range(height):
    for col in range(width):
        img[50 + row, 100 + col] = newLenaImg[row, col]

cv2.imshow('dstimg', img)
cv2.waitKey(0)

在这里插入图片描述

图片美化


亮度增强


亮度增强,其实就是将每个颜色值增大一点点 例如: color = color + 50 即可调亮图片 color = color - 50 即可调暗图片

示例代码

import cv2 as cv


def checkColor(value):
    value = value if value < 256 else 255
    value = value if value > 0 else 0
    return value


# 将图片数据读取进来
img = cv.imread("./timg.jpg", cv.IMREAD_COLOR)
cv.imshow('img', img)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]

# 定义颜色改变的值
count = 35

# 遍历每一个像素点
for row in range(height):
    for col in range(width):
        # 获取每个像素点的颜色值
        (b, g, r) = img[row, col]
        #  增大当前颜色值
        newb = b + count
        newg = g + count
        newr = r + count

        # 校验每个像素值不能越界
        newb = checkColor(newb)
        newg = checkColor(newg)
        newr = checkColor(newr)

        img[row, col] = (newb, newg, newr)
# 显示改变之后的图像
cv.imshow('newimg', img)
cv.waitKey(0)

在这里插入图片描述

灰度图片


直方图


统计每个灰度值出现的概率

示例代码

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

# 将图片数据读取进来
img = cv.imread("./timg.jpg", cv.IMREAD_COLOR)

# 将图片转成灰度图片
grayImg = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
cv.imshow("gray", grayImg)

# 计算直方图 , 注意这里需要用数组的方式传值
hist = cv.calcHist([grayImg], [0], None, [256], [0.0, 255.0])
plt.plot(hist, color="green")
plt.show()

cv.waitKey(0)
cv.destroyAllWindows()

在这里插入图片描述
备注: 使用matplotlib绘制直方图有两种方式

方式一:
    # 使用api将直方图数据计算好 图片 通道  掩膜  数量  值的范围
    hist = cv.calcHist([grayImg],[0],None,[256],[0.0,255.0])
    # 调用plot函数显示
    plt.plot(hist,color="green")
    plt.show()
方式二:
    # 1.使用Img.ravel()将多行的矩阵转成单行的矩阵
    # 2. 然后调用matplot的hist函数自动计算直方图,bins表示像素区间数量
    plt.hist(grayImg.ravel(),color="red",bins=256)
	plt.show()

直方图均衡化


直方图均衡化是将原图象的直方图通过变换函数修正为均匀的直方图,然后按均衡直方图修正原图象。图象均衡化处理后,图象的直方图是平直的,即各灰度级具有相同的出现频数,那么由于灰度级具有均匀的概率分布,图象看起来就更清晰了。

经过直方图均衡化处理之后,我们整个图像的颜色变化就是一种平滑变化的状态

原始直方图 – 均衡化直方图的 变换函数 : 累积概率图

实例代码

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

# 将图片数据读取进来
img = cv.imread("./timg.jpg", cv.IMREAD_COLOR)

# 将图片转成灰度图片
grayImg = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
cv.imshow("gray", grayImg)

# 计算直方图 , 注意这里需要用数组的方式传值
hist = cv.calcHist([grayImg], [0], None, [256], [0.0, 255.0])
plt.plot(hist, color="green")
plt.show()

# 直方图均衡化
# equalize_img = np.zeros(grayImg.shape,np.uint8)
equalize_img = cv.equalizeHist(grayImg)
cv.imshow("equalize img", equalize_img)

# 会自己统计直方图,但是需要将多行数据转成单行数据
plt.hist(equalize_img.ravel(), bins=256)
plt.show()

cv.waitKey(0)
cv.destroyAllWindows()

在这里插入图片描述

彩色图片


直方图


在前面,我们计算灰度图片的直方图时,我们只需要统计灰色值出现的概率就可以了,现在我们要处理的是彩色图片,所以我们需要将(B,G,R)三种颜色值取出来,单独计算每种颜色的直方图

示例代码

import cv2
import matplotlib.pyplot as plt

img = cv2.imread('./timg.jpg', cv2.IMREAD_LOAD_GDAL)

colors = ['blue', 'green', 'red']
img_spilt = cv2.split(img)
for i, channel in enumerate(img_spilt):
    plt.hist(channel.ravel(), bins=256, color=colors[i])
    plt.show()

cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

视频处理


视频分解图片


在机器学习中,我们需要大量的图片训练样本,这些图片训练样本如果我们全都使用相机拍照的方式去获取的话,工作量会非常巨大, 通常的做法是我们通过录制视频,然后提取视频中的每一帧即可!

ubuntu下摄像头终端可以安装: sudo apt-get install cheese 然后输入cheese即可打开摄像头

实现步骤:

  1. 加载视频
  2. 获取视频信息
  3. 解析视频

示例代码

在这里插入代码片

猜你喜欢

转载自blog.csdn.net/weixin_45946270/article/details/124610749