opencv技能树答题记录


opencv技能树答题记录以及一些扩展学习记录,记录一些比较常用的,有些感觉也用不上就没写了。

自用,持续更新

1、opencv获取图像

获取opencv版本

import cv2

print(cv2.__version__)

步骤: 读取文件下的图像->显示图像->添加窗口->释放资源

import cv2

if __name__ == '__main__':
    img = cv2.imread('../Resources/lena.png')
    cv2.imshow('demo',img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

2、图像像素颜色

OpenCV 常用的颜色空间有 RGB颜色空间、HSV颜色空间、Lab颜色空间

RGB颜色空间 红绿蓝三原色 [0-255],[0-255],[0-255]
7DBlsH.png
Hsv颜色空间 H色相 [0-179] S饱和度,0为白色[0-255] V明度,0为黑色[0-255]

LAB颜色空间 L 像素亮度 A 左绿右红 B 一端蓝另一端黄

打印图片上点的颜色空间信息,主要是三个函数

import cv2 as cv

if __name__ == '__main__':
    img = cv.imread('../Resources/lena.png', cv.COLOR_BGR2LAB)
    img1 = cv.imread('../Resources/lena.png', cv.IMREAD_COLOR)
    img2 = cv.imread('../Resources/lena.png', cv.COLOR_BGR2HSV)
    px = img[100, 100]
    px1 = img1[100, 100]
    px2 = img2[100, 100]

    print(f'L:{px[0]}, a:{px[1]}, b:{px[2]}')
    print(f'blue:{px1[0]}, green:{px1[1]}, red:{px1[2]}') #主要是要注意这里是BGR
    print(f'Hue:{px2[0]}, Saturation:{px2[1]}, Value:{px2[2]}')

修改像素值得大小从而改变图片风格

import numpy as np
import cv2
import math

def Fenggehua(img):
    height, width, channels = img.shape # 返回图像矩阵的三元素
    for i in range(0, width):
        for j in range(0, height):
            b, g, r = img[i, j] # 对三元素进行遍历
            hack_b = int(math.pow(b/256.0, 3/2) * 256)
            hack_g = int(math.pow(g/256.0, 4/5) * 256)
            hack_r = int(math.pow(r/256.0, 3/2) * 256)
            img[i, j, 0] = hack_b
            img[i, j, 1] = hack_g
            img[i, j, 2] = hack_r

if __name__ == '__main__':
    img_origin = cv2.imread('../Resources/lena.png', cv2.IMREAD_COLOR)
    img = cv2.imread('../Resources/lena.png', cv2.IMREAD_COLOR) #用于保存原图

    Fenggehua(img)

    numpy_horizontal_concat = np.concatenate((img_origin, img), axis=1) # 这里是对图像矩阵的拼接,可以实现图像的合并
    cv2.imshow('test', numpy_horizontal_concat)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

效果如下
7DDWNt.png

3、使用切片操作对图像进行处理

这里一定要注意x是列,然后y是行,y从左到右,x从右到左

首先用下面的代码来获取图像上指定位置点的像素大小

import cv2
img = cv2.imread("../Resources/lena.png")

def on_EVENT_LBUTTONDOWN(event, x, y, flags, param):
    if event == cv2.EVENT_LBUTTONDOWN:
        xy = "%d,%d" % (x, y)
        print(xy)
        cv2.circle(img, (x, y), 1, (255, 0, 0), thickness=-1)
        cv2.putText(img, xy, (x, y), cv2.FONT_HERSHEY_PLAIN,
                    1.0, (0, 0, 0), thickness=1)
        cv2.imshow("image", img)


cv2.namedWindow("image")
cv2.setMouseCallback("image", on_EVENT_LBUTTONDOWN)
cv2.imshow("image", img)

while (True):
    try:
        cv2.waitKey(100)
    except Exception:
        cv2.destroyWindow("image")
        break

cv2.waitKey(0)
cv2.destroyAllWindow()

利用鼠标的回击事件来达到目的,效果如下

使用下面的代码来实现切片的操作

import cv2

if __name__ == '__main__':
    img = cv2.imread('../Resources/ball.jpg', cv2.IMREAD_COLOR)
    start = [493, 594]
    end = [112, 213]
    ball = img[start[0]:start[1], end[0]:end[1]]
    x_step = 101
    y_step = 10
    for i in range(-1, 4):
        x_offset = x_step * i
        y_offset = y_step * i
        img[start[0] - y_offset:start[1] - y_offset, end[0] + x_offset:end[1] + x_offset] = ball

    cv2.imshow("ball_continue", img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

效果如下

4、图像灰度

import numpy as np
import cv2

if __name__ == '__main__':
    img = cv2.imread("../Resources/lena.png")
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #转为灰度图

    img_gray_by_BGR_space = cv2.cvtColor(img_gray, cv2.COLOR_GRAY2BGR)
    img_concat = np.concatenate(
        (img, img_gray_by_BGR_space),
        axis=1
    )
    cv2.imwrite("bug_band.png", img_concat)
    cv2.imshow('duibi', img_concat)

    cv2.waitKey(0)
    cv2.destroyAllWindows()

颜色转换其实是数学运算,如灰度化最常用的是:gray=R0.299+G0.587+B*0.114

图像镜像与缩放操作

使用recize函数,实现高宽指定比例缩放和倍数缩放

import cv2

img = cv2.imread('../Resources/lena.png')

# 按照指定的宽度、高度缩放图片
res = cv2.resize(img, (132, 150))
# 按照比例缩放,如x,y轴均放大一倍
res2 = cv2.resize(img, None, fx=2, fy=2, interpolation=cv2.INTER_LINEAR)

cv2.imshow('shrink', res), cv2.imshow('zoom', res2)
cv2.waitKey(0)

使用filp()函数实现图像翻转

第二个参数含义
1水平翻转
0垂直翻转
-1水平垂直翻转
import cv2

img = cv2.imread('../Resources/lena.png')

res = cv2.flip(img,1)
res2 = cv2.flip(img,0)
res3 = cv2.flip(img,-1)

cv2.imshow('shuiping', res), cv2.imshow('chuizhi', res2),cv2.imshow('shuipingchuizhi', res3)
cv2.waitKey(0)

效果如下

5、使用鼠标绘制矩形

主要是利用了鼠标的回调事件来操作,其中代码封装成一个类,可读性和扩展性较强

import numpy as np
import cv2 as cv
from random import randint


class Painter:
    def __init__(self) -> None:
        self.mouse_is_pressed = False
        self.last_pos = (-1, -1)
        self.width = 300
        self.height = 512
        self.img = np.zeros((self.width, self.height, 3), np.uint8)
        self.window_name = 'painter'
        self.color = None

    def run(self):
        print('画板,拖动鼠标绘制矩形框,按ESC退出,按c键清空画板')
        cv.namedWindow(self.window_name)
        cv.setMouseCallback(
            self.window_name,
            lambda event, x, y, flags, param: self.on_draw(
                event, x, y, flags, param
            )
        )
        while True:
            cv.imshow(self.window_name, self.img)
            k = cv.waitKey(1) & 0xFF
            if k == ord('c'):
                self.clean()
            elif k == 27:
                break

        cv.destroyAllWindows()

    def on_draw(self, event, x, y, flags, param):
        pos = (x, y)
        if event == cv.EVENT_LBUTTONDOWN:
            self.mouse_is_pressed = True
            self.last_pos = pos
        elif event == cv.EVENT_MOUSEMOVE:
            if self.mouse_is_pressed == True:
                self.begin_draw_rectangle(self.last_pos, pos)
        elif event == cv.EVENT_LBUTTONUP:
            self.end_draw_rectangle(self.last_pos, pos)
            self.mouse_is_pressed = False

    def clean(self):
        cv.rectangle(self.img, (0, 0), (self.height, self.width), (0, 0, 0), -1)

    def begin_draw_rectangle(self, pos1, pos2):
        if self.color is None:
            self.color = (randint(0, 256), randint(0, 256), randint(0, 256))
        cv.rectangle(self.img, pos1, pos2, self.color, -1)

    def end_draw_rectangle(self, pos1, pos2):
        self.color = None


if __name__ == '__main__':
    p = Painter()
    p.run()

效果如下
在这里插入图片描述

6、腐蚀膨胀开运算和闭运算

先理解下,这是后面的基础,知道这个也好理解和记忆后面的内容

  • 腐蚀就是变瘦
  • 膨胀就是变胖
  • 开运算就是先腐蚀再膨胀
  • 闭运算就是先膨胀再腐蚀
import cv2
import numpy as np

img = cv2.imread('../Resources/j.bmp')
kernel = np.ones((5, 5), np.uint8)
kernel1 = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))

erosion = cv2.erode(img, kernel)  # 腐蚀
dilation = cv2.dilate(img, kernel)  # 膨胀
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel1)  # 开运算
closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel1)  # 闭运算

img_concat = np.concatenate(
    (img,erosion, dilation,opening,closing),
    axis=1
)
cv2.imwrite("bug_band.jpg", img_concat)
cv2.imshow('connect',img_concat)

cv2.waitKey(0)
cv2.destroyAllWindows()

效果如下

结合上图可以很好的明白这四个操作的用处,可以看出开闭运算好像对图像没有什么影响

现在我们换一张图,原图中内部有很多咋点,可以看出闭运算把内部杂点消除了,但是开运算却把杂点放大了

再换一张图原图中外部有很多咋点,可以看出开运算把外部杂点消除了,但是必运算却把杂点放大了

上面的原因从步骤来考虑很快就能明白,这里不做赘述,代码如下:

import cv2
import numpy as np

img = cv2.imread('../Resources/j_noise_out.bmp')
kernel = np.ones((5, 5), np.uint8)
kernel1 = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))

opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel1)  # 开运算
closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel1)  # 闭运算

img_concat = np.concatenate(
    (img, opening,closing),
    axis=1
)
cv2.imwrite("bug_band.jpg", img_concat)
cv2.imshow('connect',img_concat)

cv2.waitKey(0)
cv2.destroyAllWindows()

7、联通区域分析

联通区域分析可以将具有相同像素值且位置相邻的前景像素点组成的图像区域识别出来

import cv2

img = cv2.imread('../Resources/2.jpg', -1)
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, th = cv2.threshold(gray_img, 127, 255, cv2.THRESH_BINARY)
ret, labels, stats, centroid = cv2.connectedComponentsWithStats(th)

# 只画出最大区域
# max_area = sorted(stats, key = lambda s : s[-1], reverse = False)[-2]
#
# cv2.rectangle(img, (max_area[0], max_area[1]), (max_area[0] + max_area[2], max_area[1] + max_area[3]), (25, 25, 255), 3)
# cv2.putText(img, str(1), (max_area[0], max_area[1] + 25), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255, 25, 25), 2)

# 搜索每一个区域
for i, stat in enumerate(stats):
    cv2.rectangle(img, (stat[0], stat[1]), (stat[0] + stat[2], stat[1] + stat[3]), (25, 25, 255), 3)
    cv2.putText(img, str(i+1), (stat[0], stat[1] + 25), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255, 25, 25), 2)

cv2.imshow('liantongquyu', img)
print(img.shape)
cv2.waitKey(0)
cv2.destroyAllWindows()

效果如下,可以看出对于区域比较明显的图像可以将去区分出来

8、寻找图像的轮廓

轮廓是由连续的点组成的曲线。轮廓与边缘很相似,但轮廓是连续的,边缘不一定都连续。轮廓反映了物体的基本外形,常用于形状分析和物体的检测和识别。OpenCV 提供函数 cv.findContours() 对二值图像寻找轮廓,函数 cv2.drawContours() 绘制轮廓。

import cv2 as cv

if __name__ == '__main__':
    img = cv.imread("../Resources/3.jpg", flags=1)
    imgGray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

    ret, thresh = cv.threshold(imgGray, 127, 255, cv.THRESH_BINARY_INV)
    contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
    contourPic = cv.drawContours(img, contours, -1, (0, 0, 255), 2)

    cv.imshow("ContourPicture", contourPic)
    cv.waitKey(0)

首先将图像转为灰度,再用大津法进行二值化,之后使用findContours函数进行轮廓查找,之后再用drawContours函数进行绘制轮廓,就这么几部了
效果如下

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

桃成蹊2.0

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

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

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

打赏作者

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

抵扣说明:

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

余额充值