零基礎小白必看:教你在python畫不同顏色的畫布,簡單好玩


文章目錄

  • 摘要
  • numpy的ndarray數據結構的索引與賦值
  • 創建空白畫布
  • 初始化白色的畫布
  • 初始化彩色的畫布
  • 利用cv2的內置方法merge與split 利用numpy內置的索引
  • 綜合實驗-初始化背景
  • 「❤️ 感謝大家」

摘要

在這篇文章中將給大家講解如何分別用numpy的方法,與numpy與cv2結合的方法創建空白畫布,創建白色畫布,與創建彩色畫布。在講解過程中還會介紹cv2進行通道分割cv2.split與通道合並cv2.merge的兩個函數的具體使用以及深究numpy的ndarray數據結構的索引與賦值。

 

這里多說一句,小編是一名python開發工程師,這里有我自己整理了一套最新的python系統學習教程,包括從基礎的python腳本到web開發、爬蟲、數據分析、數據可視化、機器學習等。想要這些資料的可以進裙930900780領取。

numpy的ndarray數據結構的索引與賦值

在使用畫圖工具的時候, 第一件事情就是創建一個新的空白畫布,我們可以指定畫布的大小和顏色。

那我們如何使用opencv來創建一個空白的畫布(值相同的圖片) ?

其實image的數據結構上的圖片,本質上就是numpy里面的ndarray的對象,創建一個畫布本質上就是創建一個同等規格的ndarray。

創建一個新的特定尺寸的ndarray我們可以使用np.zeors 函數,我們將圖像的高度(height),圖像的寬度(width),以及圖像的通道數channel 以tuple 類型傳入np.zeros。再次聲明是tuple類型

另外由於不是所有的numpy類型的數值,都可以放到opencv中進行圖像處理.

數值取值范圍在0-255, 我們需要指定數據類型為uint8 unsigned integer 8-bit

np.zeros((height, width, channels), dtype="uint8")
1
復制代碼

舉個例子:想創建一個800 x 600 x 3 的圖片,一個BGR格式的圖像,我們就得這么寫:

# 初始化一個空畫布 300×300 三通道 背景色為黑色 
canvas_black = np.zeros((600, 800, 3), dtype="uint8")
12
復制代碼

得到的效果如下:

 

注意: height寫在前面
為什么Height寫在前面?
就得知道opencv圖像的數據結構是numpy,Image的屬性,其實就是numpy的ndarray數據格式的屬性。

我們可以直接獲取img對象的諸多屬性,例如我們打印lena圖的屬性,具體如下:

 

 # -*- coding: utf-8 -*- 
import numpy as np
import cv2

# 導入一張圖像 模式為彩色圖片
img = cv2.imread('lena.jpg', cv2.IMREAD_COLOR)

print("================打印圖像的屬性================")
print("圖像對象的類型 {}".format(type(img)))
print(img.shape)
print("圖像寬度: {} pixels".format(img.shape[1]))
print("圖像高度: {} pixels".format(img.shape[0]))
print("通道: {}".format(img.shape[2]))
print("圖像分辨率: {}".format(img.size))
print("數據類型: {}".format(img.dtype))
123456789101112131415
復制代碼

輸出結果

================打印圖像的屬性================
圖像對象的類型 <class 'numpy.ndarray'>
(256, 256, 3)
圖像寬度: 256 pixels
圖像高度: 256 pixels
通道: 3
圖像分辨率: 196608
數據類型: uint8
12345678
復制代碼

有時候我們也可以偷懶,如果我們想創建與另外一個圖像尺寸相同的畫布的時候,我們可以使用np.zeros_like

canvas_black = np.zeros_like(img)
1
復制代碼

創建空白畫布

創建空白畫布的函數如下:

def InitCanvas(width, height, color=(255, 255, 255)):
    canvas = np.ones((height, width, 3), dtype="uint8")
    canvas[:] = color
    return canvas
1234
復制代碼

調用的時候傳入圖像的寬度、高度和畫布的顏色。例如創建一個800*600 顏色為純黑色的畫布:

canvas = InitCanvas(800, 600, color=(255,255,255))
1
復制代碼

創建空白畫布的完整代碼如下:

'''
初始化畫布
'''
import cv2
import numpy as np

def init_canvas(width, height, color=(255, 255, 255)):
    canvas = np.ones((height, width, 3), dtype="uint8")
    canvas[:] = color
    return canvas

canvas = init_canvas(200, 200, color=(125, 40, 255))

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

cv2.destroyAllWindows()
1234567891011121314151617
復制代碼

效果展示:

 

初始化白色的畫布

白色的畫布, 因為比較簡單,而且三個通道的值都相同。

ps: 其實灰色的圖片(GRAY2BGR),三個通道的值都相同。

那么我們創建一個全都是1的矩陣,然后乘上某個數值,問題是不是就解決了。

我們需要用到np.ones 函數

# 初始化一個空畫布 300×300 三通道 背景色為白色 
canvas_white = np.ones((300, 300, 3), dtype="uint8")
12
復制代碼

接下來, 需要乘上一個整數,255 (你可以填入0-255的任意值)

canvas_white *= 255
1
復制代碼

這種運算稱之為 全局乘法 。

具體代碼如下:

import cv2
import numpy as np
canvas_white = np.ones((300, 300, 3), dtype="uint8")
canvas_white *= 255
cv2.imshow('canvas', canvas_white)
cv2.waitKey(0)
cv2.destroyAllWindows()
1234567
復制代碼

創建的白色畫布如下

 

初始化彩色的畫布

利用cv2的內置方法merge與split

我們初始化BGR的圖片canvas_white 之后將原來的圖片進行通道分離,之后分別乘上BGR三個通道的整數值,然后將三個通道合並在一起,就得到我們想要的彩圖純色背景。

那通道的分離我們需要用到的函數是cv2.split(img).

# 將原來的三個通道抽離出來, 分別乘上各個通道的值
(channel_b, channel_g, channel_r) = cv2.split(canvas)
12
復制代碼

channel_b 藍色通道channel_g 綠色通道channel_r 紅色通道,都是二維的ndarray對象。

我們指定一種顏色,例如 color = (100, 20, 50))

注意:我們這里的顏色指的BGR格式

也就是

B -> 100
G -> 20
R -> 50

接下來我們分別將其乘上對應的值.

# 顏色的值與個通道的全1矩陣相乘
channel_b *= color[0]
channel_g *= color[1]
channel_r *= color[2]
1234
復制代碼

接下來我們將三個通道重新合並,需要用到的函數是cv2.merge

cv2.merge([channel_b, channel_g, channel_r])
1
復制代碼

注意:三個通道的矩陣以list [] 的方式傳入merge函數.

綜合起來,就是我們的第一個初始化彩色背景的函數

# 初始化一個彩色的畫布 - cv2版本
def init_canvas(width, height, color=(255, 255, 255)):
    canvas = np.ones((height, width, 3), dtype="uint8")

    # 將原來的三個通道抽離出來, 分別乘上各個通道的值
    (channel_b, channel_g, channel_r) = cv2.split(canvas)
    # 顏色的值與個通道的全1矩陣相乘
    channel_b *= color[0]
    channel_g *= color[1]
    channel_r *= color[2]

    # cv.merge 合並三個通道的值
    return cv2.merge([channel_b, channel_g, channel_r])
12345678910111213
復制代碼

具體實現代碼如下:

'''
初始化畫布
'''
import cv2
import numpy as np

# 初始化一個彩色的畫布 - cv2版本
def init_canvas(width, height, color=(255, 255, 255)):
    canvas = np.ones((height, width, 3), dtype="uint8")

    # 將原來的三個通道抽離出來, 分別乘上各個通道的值
    (channel_b, channel_g, channel_r) = cv2.split(canvas)
    # 顏色的值與個通道的全1矩陣相乘
    channel_b *= color[0]
    channel_g *= color[1]
    channel_r *= color[2]

    # cv.merge 合並三個通道的值
    return cv2.merge([channel_b, channel_g, channel_r])

canvas = init_canvas(200, 200, color=(125, 100, 255))

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

cv2.destroyAllWindows()
1234567891011121314151617181920212223242526
復制代碼

運行效果:

 

注意:此函數使用 cv2.split 非常耗時 所以只有在需要的時候才能做到。 否則用Numpy索引。

利用numpy內置的索引

使用numpy原生的方法, 性能會比opencv中的要好。我們直接使用numpy的ndarray的索引的方法。

例如 canvas[:,:,0] 選中的是所有行,所有列,像素元素的第一個值,也就是,所有B通道的值。

然后對其進行賦值:

canvas[:,:,0] = color[0]
1
復制代碼

完整版本的函數如下,B/G/R通道分別進行賦值:

def init_canvas(width, height, color=(255, 255, 255)):
    canvas = np.ones((height, width, 3), dtype="uint8")
    # Blue 
    canvas[:,:,0] = color[0]
    # Green
    canvas[:,:,1] = color[1]
    # Red
    canvas[:,:,2] = color[2]

    return canvas
12345678910
復制代碼

具體實現代碼如下:

'''
初始化畫布
'''
import cv2
import numpy as np

def init_canvas(width, height, color=(255, 255, 255)):
    canvas = np.ones((height, width, 3), dtype="uint8")
    # Blue 
    canvas[:,:,0] = color[0]
    # Green
    canvas[:,:,1] = color[1]
    # Red
    canvas[:,:,2] = color[2]

    return canvas

canvas = init_canvas(200, 200, color=(125, 100, 255))

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

cv2.destroyAllWindows()
1234567891011121314151617181920212223
復制代碼

運行實現的效果和第一種方法一樣:

 


實際上我們還有更快的方法, 可以實現這個功能, 這就需要你熟練掌握Numpy的使用技巧.

我們可以直接賦值color

canvas[:] = color
1
復制代碼

完整實現過程如下:

'''
初始化畫布
'''
import cv2
import numpy as np

def init_canvas(width, height, color=(255, 255, 255)):
    canvas = np.ones((height, width, 3), dtype="uint8")
    canvas[:] = color
    return canvas

canvas = init_canvas(200, 200, color=(125, 40, 255))

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

cv2.destroyAllWindows()
1234567891011121314151617
復制代碼

運行的效果:

 

綜合實驗-初始化背景

在這個綜合實驗里會分別用上述的方法,創建黑色背景,白色背景,彩色背景。

具體代碼如下:

'''
初始化一個空白的畫布
並指定畫布的顏色
'''

import cv2
import numpy as np

# 初始化一個空畫布 300×300 三通道 背景色為黑色 
canvas_black = np.zeros((300, 300, 3), dtype="uint8")
cv2.imshow("canvas_black", canvas_black)

# 初始化一個空畫布 300×300 三通道 背景色為白色 
canvas_white = np.ones((300, 300, 3), dtype="uint8")
canvas_white *= 255

cv2.imshow("canvas_white", canvas_white)

'''
初始化一個彩色的畫布 - cv2版本
此函數使用 cv2.split 非常耗時 所以只有在需要的時候才能做到。 否則用Numpy索引。

'''
def InitCanvasV1(width, height, color=(255, 255, 255)):
    canvas = np.ones((height, width, 3), dtype="uint8")

    # 將原來的三個通道抽離出來, 分別乘上各個通道的值
    (channel_b, channel_g, channel_r) = cv2.split(canvas)
    # 顏色的值與個通道的全1矩陣相乘
    channel_b *= color[0]
    channel_g *= color[1]
    channel_r *= color[2]

    # cv.merge 合並三個通道的值
    return cv2.merge([channel_b, channel_g, channel_r])

'''
初始化一個彩色的畫布 - numpy版本
使用numpy的索引 賦值
'''
def InitCanvasV2(width, height, color=(255, 255, 255)):
    canvas = np.ones((height, width, 3), dtype="uint8")
    # Blue 
    canvas[:,:,0] = color[0]
    # Green
    canvas[:,:,1] = color[1]
    # Red
    canvas[:,:,2] = color[2]

    return canvas

'''
初始化終極版本

熟練掌握 numpy 才可以提高工作效率哦
'''
def InitCanvasV3(width, height, color=(255, 255, 255)):
    canvas = np.ones((height, width, 3), dtype="uint8")
    canvas[:] = color
    return canvas

# 初始化一個彩色的畫布
canvas_color = InitCanvasV2(300, 300, color=(100, 20, 50))
cv2.imshow("canvas_color", canvas_color)

# 等待e鍵按下 關閉所有窗口
while cv2.waitKey(0) != ord('e'):
    continue
cv2.destroyAllWindows()

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
復制代碼

運行結果:

 

最后多說一句,小編是一名python開發工程師,這里有我自己整理了一套最新的python系統學習教程,包括從基礎的python腳本到web開發、爬蟲、數據分析、數據可視化、機器學習等。想要這些資料的可以進裙930900780領取。

 

本文章素材來源於網絡,如有侵權請聯系刪除。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM