5

快速学完OpenCV+python计算机视觉图像处理(四)

 3 years ago
source link: https://blog.csdn.net/weixin_41529012/article/details/117479111
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

返回主目录

4 图像基本特效

4-1 图像特效介绍

图像特效分为以下几个,分别是:

  1. 毛玻璃效果

4-2 图像灰度处理1

灰度处理常用方法:

  • 方法1,直接使用imread里面的参数,代码如下:
import cv2
src = cv2.imread('17.jpg', 1)
gray1 = cv2.imread('17.jpg', 0)
gray2 = cv2.imread('17.jpg', cv2.IMREAD_GRAYSCALE)
print(src.shape)
print(gray1.shape)
print(gray2.shape)
cv2.imshow('src', src)
cv2.imshow('gray1', gray1)
cv2.imshow('gray2', gray2)
cv2.waitKey(0)

运行结果如下:

(308, 204, 3)
(308, 204)
(308, 204)

在这里插入图片描述

  • 方法2,使用OpenCV里面的cvtColor将RGB图像转换为灰度图像,代码如下:
import cv2

src = cv2.imread('17.jpg', 1)
cv2.imshow('src', src)
gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
cv2.imshow('gray', gray)
cv2.waitKey(0)

运行结果如下:
在这里插入图片描述

4-3 图像灰度处理2

  • 方法3,将RGB3个维度的数相加除以3,这就是均值算法Average,代码如下:
import cv2
import numpy as np

img = cv2.imread('16.jpg', 1)
cv2.imshow('src', img)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]

dst = np.zeros((height, width, 3), np.uint8)
for i in range(0, height):
    for j in range(0, width):
        (b, g, r) = img[i, j]
        gray = (int(b) + int(g) + int(r)) / 3
        dst[i, j] = np.uint8(gray)

cv2.imshow('dst', dst)
cv2.waitKey(0)

运行结果如下:
在这里插入图片描述

  • 方法4,使用特定公式gray = r0.299+g0.587+b*0.114将RGB图像转换为灰度图像,这公式叫做亮度算法Luminosity,除了亮度算法和均值算法求灰度图像,还有一种明度算法Lightness也是可以将彩色图像转换为灰度图像的。亮度算法代码如下:
import cv2
import numpy as np

img = cv2.imread('15.jpg', 1)
cv2.imshow('src', img)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]

dst = np.zeros(imgInfo, np.uint8)

for i in range(0, height):
    for j in range(0, width):
        (b, g, r) = img[i, j]
        b = int(b)	# 这里如果不做取整,就会溢出,导致图像变得不伦不类
        g = int(g)
        r = int(r)
        gray = r * 0.299 + g * 0.587 + b * 0.114
        dst[i, j] = np.uint8(gray)
cv2.imshow('dst', dst)
cv2.waitKey(0)

运行结果如下:
在这里插入图片描述

  • 方法5,使用明度算法Lightness将彩色图像转换为灰度图像,代码如下:
import cv2
import numpy as np

img = cv2.imread('14.jpg', 1)
cv2.imshow('src', img)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]

dst = np.zeros(imgInfo, np.uint8)  # 新建一个空模板

for i in range(0, height):
    for j in range(0, width):
        b, g, r = img[i, j]
        b = int(b)
        g = int(g)
        r = int(r)
        gray = (max(r, g, b) + min(r, g, b)) / 2
        dst[i, j] = np.uint8(gray)

cv2.imshow('dst', dst)
cv2.waitKey(0)

运行结果如下:
在这里插入图片描述

以下将Luminosity(亮度)、Lightness(明度)、Average(均值)三个算法公式列在下面:

Gray_Luminosity = R*0.299 + G*0.587 + B*0.114
Gray_Lightness = (max(R, G, B) + min(R, G, B)) / 2
Gray_Average = (R + G + B) / 3

4-4 算法优化

代码如下:

import cv2
import numpy as np
import datetime

img = cv2.imread('13.jpg')
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
dst = np.zeros(imgInfo, np.uint8)
oldtime = datetime.datetime.now()
for i in range(0, height):
    for j in range(0, width):
        b, g, r = img[i, j]
        b = int(b)
        g = int(g)
        r = int(r)
        # r*0.299+g*0.587+b*0.114=((r*0.299+g*0.587+b*0.114)*2^2)*2^-2
        # =(r*1.196+g*2.348+b*0.456)*2^-2约等于(r*1+g*2+b*1)*2^-2
        # 进行二进制位移转换=(r+(b<<1)+b)>>2
        gray = (r + (b << 1) + b) >> 2
        dst[i, j] = np.uint8(gray)
newtime = datetime.datetime.now()
print('after optimize', newtime - oldtime)
cv2.imshow('dst', dst)
cv2.waitKey(0)

运行结果如下:

before optimize: 0:00:00.261156
after optimize: 0:00:00.203124

从运行结果可以看出,优化后的时间要比优化之前快那么一点点。

4-5 颜色反转

  1. 灰度图像反转

代码如下:

import cv2
import numpy as np

img = cv2.imread('12.jpg', 1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imshow('gray', gray)
dst = np.zeros(gray.shape, np.uint8)
dst2 = np.zeros((height, width, 1), np.uint8)

for i in range(0, height):
    for j in range(0, width):
        grayPixel = gray[i, j]
        dst[i, j] = 255 - grayPixel

cv2.imshow('dst', dst)
cv2.waitKey(0)

运行结果如下:
在这里插入图片描述

  1. 彩色图像反转

代码如下:

import cv2
import numpy as np

img = cv2.imread('12.jpg', 1)
# cv2.imshow('img', img)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
dst = np.zeros(img.shape, np.uint8)
dst2 = np.zeros((height, width, 3), np.uint8)

for i in range(0, height):
    for j in range(0, width):
        b, g, r = img[i, j]
        b2 = int(b)
        g2 = int(g)
        r2 = int(r)
        dst[i, j] = (255 - b, 255 - g, 255 - r)
        dst2[i, j] = (255 - b2, 255 - g2, 255 - r2)

cv2.imshow('dst', dst)
cv2.imshow('dst2', dst2)
cv2.waitKey(0)

运行结果如下:
在这里插入图片描述

4-6 马赛克

源代码如下:

import cv2

img = cv2.imread('17.jpg', 1)
cv2.imshow('img', img)

imgInfo = img.shape
print(imgInfo)

height = imgInfo[0]
width = imgInfo[1]

for m in range(140, 180):  # 高,选取图像(100,140)->(150,180)这片区域
    for n in range(100, 150):  # 宽
        if m % 10 == 0 and n % 10 == 0:  # 针对这片区域的10*10小方格进行筛选
            for i in range(0, 10):
                for j in range(0, 10):
                    b, g, r = img[m, n]  # 选择在m->n这个区域的原图像
                    img[i + m, j + n] = b, g, r  # 将m->n这个区域的原图像每一块10*10区域和第一个位置的相同
cv2.imshow('dst', img)
cv2.waitKey(0)

运行结果如下:
在这里插入图片描述

4-7 毛玻璃

代码如下:

import cv2
import numpy as np

img = cv2.imread('1.jpg', 1)
cv2.imshow('img', img)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
dst = np.zeros((height, width, 3), np.uint8)
mn = 6
for m in range(0, height - mn):  # 为了防止溢出需要减去6
    for n in range(0, width - mn):
        index = int(np.random.random() * 6)
        dst[m, n] = img[m + index, n + index]

cv2.imshow('dst', dst)
cv2.waitKey(0)

运行结果如下:
在这里插入图片描述

4-8 图片融合

代码如下:

# dst = src1 * α + src2 * (1 - α)
import cv2
import numpy as np

img1 = cv2.imread('1.jpg')
img2 = cv2.imread('2.jpg')
img1Info = img1.shape
height = img1Info[0]
width = img1Info[1]

# ROI   # 这个要不要无所谓
# roiH = int(height * 0.5)
# roiW = int(width * 0.5)
# img1ROI = img1[0:roiH, 0:roiW]
# img2ROI = img2[0:roiH, 0:roiW]

# dst
dst = np.zeros((height, width, 3), np.uint8)
# dst2 = np.zeros((roiH, roiW, 3), np.uint8)
dst = cv2.addWeighted(img1, 0.4, img2, 0.6, 0)
# dst2 = cv2.addWeighted(img1ROI, 0.5, img1ROI, 0.5, 0)
cv2.imshow('dst', dst)
# cv2.imshow('dst2', dst2)
cv2.waitKey(0)

运行结果如下:
在这里插入图片描述

4-9 边缘检测1

这里讲的边缘检测算子是Canny算子,Canny 的目标是找到一个最优的边缘检测算法,其原型为:

edge = cv2.Canny(image, threshold1, threshold2[, edges[, apertureSize[, L2gradient ]]]) 

必要参数:

  • 第一个参数是需要处理的原图像,该图像必须为单通道的灰度图;
  • 第二个参数是低阈值,小于这个值时,像素值排除 ;
  • 第三个参数是高阈值,大于这个值时,像素值保留为边缘像素;
  • 注:当像素值位于两个阈值中间时,该像素仅仅在连接到一个高于高阈值的像素时被保留。

代码如下:

import cv2

# 边缘检测分为3个步骤:1.BGR2Gray;2.GaussianBlur;3.Canny
img = cv2.imread('3.jpg')
cv2.imshow('img', img)
# 1.将彩色图像转换为灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 2.将灰度图像通过高斯滤波进行平滑处理
gauss = cv2.GaussianBlur(gray, (5, 5), 0)  # 核大小必须是奇数,最后一个参数0代表高斯核标准偏差
# 3.利用Canny算子检测出边缘
dst = cv2.Canny(gauss, 100, 110)  # 第二个和第三个是最小最大阈值,一般都是经验值
cv2.imshow('canny', dst)
cv2.waitKey(0)

运行结果如下:
在这里插入图片描述

4-10 边缘检测2

这里使用边缘检测算子是Soble算子,Sobel 算子是一个主要用作边缘检测的离散微分算子 (discrete differentiation operator)。Sobel算子结合了高斯平滑和微分求导,用来计算图像灰度函数的近似梯度。

代码如下:

import cv2
import numpy as np
import math

img = cv2.imread('5.jpg', 1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
cv2.imshow('src', img)

# sobel:1.算子模板;2.图片卷积;3.阈值判决
# [1 2 1          [ 1 0 -1
#  0 0 0            2 0 -2
# -1 -2 -1 ]       1 0 -1 ]

# [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):  # 因为卷积核实3*3,这里需要减去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  # 垂直变化:将灰度图像与3*3内核进行卷积
        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]  # 水平变化:将灰度图像与3*3内核进行卷积
        grad = math.sqrt(gx * gx + gy * gy)  # 这里用G=sqrt(Gx^2+Gy^2)来求近似梯度
        grad = math.fabs(gx) + math.fabs(gy)  # 也可以用G=|Gx|+|Gy|求近似梯度
        if grad > 100:  # 大于100的设置为边缘,值越小检测的边缘越浓密
            dst[i, j] = 255  # 255为白色
        else:  # 小于100的不是边缘
            dst[i, j] = 0  # 0为黑色
cv2.imshow('dst', dst)
cv2.waitKey(0)

运行结果如下:
在这里插入图片描述

4-11 浮雕效果

运行代码如下:

import cv2
import numpy as np

img = cv2.imread('7.jpg', 1)
cv2.imshow('img', img)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# newP = grayP0 - grayP1 + 150
dst = np.zeros((height, width, 1), np.uint8)
for i in range(0, height):
    for j in range(0, width - 1):
        grayP0 = int(gray[i, j])
        grayP1 = int(gray[i, j + 1])
        newP = grayP0 - grayP1 + 150
        if newP > 255:
            newP = 255
        if newP < 0:
            newP = 0
        dst[i, j] = newP
cv2.imshow('dst', dst)
cv2.waitKey(0)

运行结果如下:
在这里插入图片描述

4-12 颜色映射

代码如下:

import cv2
import numpy as np

img = cv2.imread('8.jpg', 1)
cv2.imshow('src', img)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]

dst = np.zeros((height, width, 3), np.uint8)
for i in range(0, height):
    for j in range(0, width):
        (b, g, r) = img[i, j]
        b = 1.1 * b
        g = 1.1 * g
        r = 6.6 * r
        if b > 255:
            b = 255
        if g > 255:
            g = 255
        if r > 255:
            r = 255
        dst[i, j] = (b, g, r)
cv2.imshow('dst', dst)
cv2.waitKey(0)

运行结果如下:
在这里插入图片描述
哈哈哈,给我们的小姐姐染了个红发

4-13 油画特效

优化特效步骤如下:

  1. 彩色图片转换为灰度图片;
  2. 将图片分割为若干个小方块,统计这些小方块中每一个像素的灰度值(eg:77或者1010的小方块);
  3. 将0~255划分为几个等级,将第二步的结果映射过来分为不同的等级段中,
  4. 找到每个方块中灰度等级最多的像素,并且求取像素的均值。
  5. 将统计出来的平均值替换原来的像素值,最终来实现优化效果
    代码如下:
import cv2
import numpy as np

img = cv2.imread('6.jpg', 1)
cv2.imshow('img', img)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
dst = np.zeros((height, width, 3), np.uint8)
for i in range(4, height - 4):
    for j in range(4, width - 4):
        array1 = np.zeros(8, np.uint8)
        for m in range(-4, 4):
            for n in range(-4, 4):
                p1 = int(gray[i + m, j + n] / 32)
                array1[p1] = array1[p1] + 1
        currentMax = array1[0]
        l = 0
        for k in range(0, 8):
            if currentMax < array1[k]:
                currentMax = array1[k]
                l = k
        # 简化 均值
        for m in range(-4, 4):
            for n in range(-4, 4):
                if (gray[i + m, j + n] >= (l * 32)) and (gray[i + m, j + n] <= ((l + 1) * 32)):
                    (b, g, r) = img[i + m, j + n]
        dst[i, j] = (b, g, r)
cv2.imshow('dst', dst)
cv2.waitKey(0)

运行结果如下:

在这里插入图片描述

4-14 线段绘制

绘制线段要用到cv2.line()函数,函数原型为img=cv.line(img, pt1, pt2, color[, thickness[, lineType[, shift]]]),主要参数如下:

  • img:源图像
  • pt1:直线起点
  • pt2:直线终点
  • color:需要传入的颜色
  • thickness:线条的粗细,默认值是1
  • linetype:线条的类型,8 连接,抗锯齿等。默认情况是 8 连接。cv2.LINE_AA 为抗锯齿,这样看起来会非常平滑。

代码如下:

import cv2

img = cv2.imread('9.jpg', 1)
cv2.imshow('img', img)

# 绘制线段 1.dst;2.begin;3.end;4.color;5.width;6.type
cv2.line(img, (260, 150), (350, 180), (0, 255, 0), 18, cv2.LINE_AA)

# 绘制三角形
cv2.line(img, (300, 450), (200, 380), (0, 255, 255), 38, cv2.LINE_AA)
cv2.line(img, (200, 380), (400, 380), (0, 255, 255), 38, cv2.LINE_AA)
cv2.line(img, (400, 380), (300, 450), (0, 255, 255), 38, cv2.LINE_AA)

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

运行结果如下:
在这里插入图片描述

4-15 矩形圆形任意多边形绘制

绘制圆形用到的是cv2.circle(),绘制椭圆用到的是cv2.ellipse(),绘制长方形用到的是cv2.rectangle()

cv2.polylines() 可以用来画很多条线。只把想画的线放在一 个列中将列传给函数就可以了。每条线会独立绘制。会比用 cv2.line() 一条一条的绘制快一些。

运行代码如下:

import cv2
import numpy as np

img = cv2.imread('00.jpg', 1)
# rectangle是来画矩形框的,其中:1.src;2.左上角;3.右下角;4.color;5.如果为-1,则fill,如果>0则表示line width
cv2.rectangle(img, (180, 300), (300, 400), (0, 255, 255), -1)

# circle是用来画圆的,其中:1.src;2.center;3.r;4.color,5.同rectangle
cv2.circle(img, (240, 160), 80, (0, 255, 0), 2)

# ellipse是用来画椭圆的,其中:1.src;2.中心坐标;3.长、短轴长度;4.椭圆旋转角度;5.6.椭圆弧起始和终止角度;7.color;8.线宽或填充
cv2.ellipse(img, (410, 130), (100, 70), 80, 0, 360, (0, 0, 255), 3)

# polylines画多边形
points = np.array([[358, 54], [385, 120], [357, 163], [401, 165], [433, 237],
                   [440, 165], [485, 166], [442, 119], [442, 28], [411, 84]],
                  np.int32)  # 这个数组必须为int32
print(points.shape)  # (10, 2)
# 这里reshape的第一个参数为-1,表明这一维度的长度是根据后面的维度计算出来的
points = points.reshape((-1, 1, 2))
print(points.shape)  # (10, 1, 2)
# 1.src;2.point;3.True表示闭合的线,False不闭合;4.color;5.只有线宽,-1报错不会填充
cv2.polylines(img, [points], True, (0, 255, 255), 3)

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

运行结果如下:
在这里插入图片描述

4-16 文字图片绘制

代码如下:

import cv2

img = cv2.imread('00.jpg', 1)
font = cv2.FONT_HERSHEY_SIMPLEX  # 文字的字体类型,FONT_HERSHEY_SIMPLEX表示正常大小无衬线字体
# putText显示文本,其中:1.src;2.text;3.org;4.font;5.text size;6.color;7.line width;8.style
cv2.putText(img, 'I Love You', (300, 350), font, 1, (255, 0, 0), 2, cv2.LINE_AA)
cv2.imshow('img', img)
cv2.waitKey(0)

运行结果如下:

在这里插入图片描述


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK