1. 程式人生 > >【震驚】手把手教你用python做繪圖工具(一)

【震驚】手把手教你用python做繪圖工具(一)

在這篇部落格裡將為你介紹如何通過numpy和cv2進行結和去建立畫布,包括空白畫布、白色畫布和彩色畫布。建立畫布是製作繪圖工具的前提,有了畫布我們就可以在畫布上盡情的揮灑自己的藝術細胞。 還在為如何去繪圖煩惱的小夥伴趕緊看過來,這裡手把手教你解決問題~~~~ 當然還是講究一下規則:先點贊再看,尊重一下作者。年輕人還是要講點武德的。。。 ![](https://img2020.cnblogs.com/blog/2161629/202011/2161629-20201129104029953-1377317066.png) 廢話不多說,進入正題→→→ # 1.建立空白畫布 定義一個函式傳入影象的寬度、高度和畫布的顏色,空白畫布顏色傳入的RGB值為(255,255,255),具體函式如下: ``` def InitCanvas(width, height, color=(255, 255, 255)): canvas = np.ones((height, width, 3), dtype="uint8") canvas[:] = color return canvas ``` 例如:在這個空白的畫布上建立500*500顏色為純黑色的畫布,可表示為: `canvas = InitCanvas(500, 500, color=(0,0,0))` 實現完整程式碼如下: ``` ''' 初始化畫布 ''' import cv2 import numpy as np def InitCanvas(width, height, color=(255, 255, 255)): canvas = np.ones((height, width, 3), dtype="uint8") canvas[:] = color return canvas canvas = InitCanvas(500, 500, color=(0, 0, 0)) cv2.imshow('canvas', canvas) cv2.waitKey(0) cv2.destroyAllWindows() ``` ![](https://img2020.cnblogs.com/blog/2161629/202011/2161629-20201129104136969-1281102114.png) > 可能有些人不能理解話不要建立原理,下面進行講解: > 1、建立一個畫布本質上就是建立一個同等規格的 numpy 的 ndarray 物件; > 2、建立一個新的特定尺寸的 ndarray 可以使用 np.zeors 函式, 我們將影象的高度(height), 影象的寬度(width)以及影象的通道數channel 以tuple 型別傳入np.zeros 。 再次宣告是tuple型別 > 3、另外由於不是所有的numpy型別的數值都可以放到opencv中進行影象處理,所以數值取值範圍在0-255, 需要指定資料型別為uint8 unsigned integer 8-bit > 具體實現: > `np.zeros((height, width, channels), dtype="uint8")` # 2.初始化白色的畫布 ## 方法一 在建立的空白畫布的顏色修改為(255,255,255),即可得到白色的畫布,具體程式碼如下: ``` import cv2 import numpy as np def InitCanvas(width, height, color=(255, 255, 255)): canvas = np.ones((height, width, 3), dtype="uint8") canvas[:] = color return canvas canvas = InitCanvas(500, 500, color=(255, 255, 255)) cv2.imshow('canvas', canvas) cv2.waitKey(0) cv2.destroyAllWindows() ``` ![](https://img2020.cnblogs.com/blog/2161629/202011/2161629-20201129104253799-5906529.png) ## 方法二 首先想到的是白色,又因為比較簡單,三個通道的值都相同。 > ps: 其實灰色的圖片(GRAY2BGR), 三個通道的值都相同. 那麼我們建立一個全都是1的矩陣,然後,乘上某個數值,問題是不是就解決了。 我們需要用到np.ones 函式 ``` # 初始化一個空畫布 500×500 三通道 背景色為白色 canvas = np.ones((500, 500, 3), dtype="uint8") ``` 接下來, 需要乘上一個整數255 (你可以填入0-255的任意值) `canvas_white *= 255` 完整實現程式碼如下,結果和方法一一樣: ``` import cv2 import numpy as np canvas = np.ones((500, 500, 3), dtype="uint8") canvas *= 255 cv2.imshow('canvas', canvas) cv2.waitKey(0) cv2.destroyAllWindows() ``` # 3. 初始化彩色的畫布 ## 3.1 利用cv2的內建方法merge與split 我們初始化BGR的圖片canvas之後將原來的圖片進行通道分離,分別乘上BGR三個通道的整數值,然後將三個通道合併在一起,就得到我們想要的彩圖純色背景。 那通道的分離需要用到的函式是cv2.split(img),具體用法如下: ``` # 將原來的三個通道抽離出來, 分別乘上各個通道的值 (channel_b, channel_g, channel_r) = cv2.split(canvas) ``` * channel_b 藍色通道 * channel_g 綠色通道 * channel_r 紅色通道 * 都是二維的ndarray物件 我們指定一種顏色, 例如 color = (140, 30, 60)) 注意, 我們這裡的顏色指的BGR格式 也就是 * B -> 140 * G -> 30 * R -> 60 接下來分別將其乘上對應的值 ``` # 顏色的值與個通道的全1矩陣相乘 channel_b *= color[0] channel_g *= color[1] channel_r *= color[2] ``` 接下來我們將三個通道重新合併,需要用到的函式是cv2.merge,具體用法如下: `cv2.merge([channel_b, channel_g, channel_r])` > 注意:三個通道的矩陣以list [] 的方式傳入merge函式. 綜合以上初始化彩色背景的函式可表示為: ``` ''' 初始化畫布 ''' import cv2 import numpy as np # 初始化一個彩色的畫布 - cv2版本 def InitCanvas(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 = InitCanvas(500, 500, color=(140, 30,60)) cv2.imshow('canvas', canvas) cv2.waitKey(0) cv2.destroyAllWindows() ``` ![](https://img2020.cnblogs.com/blog/2161629/202011/2161629-20201129104521490-1844907894.png) `canvas = InitCanvas(500, 500, color=(140, 30,60))` 裡面的color可以自己自定義0-255之間的值。 ## 3.2 利用numpy內建的索引 以上的方法建立起來非常的耗時,對於追求完美的小夥伴們可能不會去使用這種方法。那麼來了,還有另外一種方法: 使用numpy原生的方法效能會比opencv中的要好。 可以直接使用numpy的ndarray的索引的方法。 例如 : `canvas[:,:,0]` 選中的是所有行和所有列畫素元素的第一個值,也就是, 所有B通道的值. 然後對其進行賦值: `canvas[:,:,0] = color[0]` 具體使用如圖: ![](https://img2020.cnblogs.com/blog/2161629/202011/2161629-20201129104601314-955837722.png) 完整使用的程式碼如下: ``` ''' 初始化畫布 ''' import cv2 import numpy as np def InitCanvas(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 = InitCanvas(500, 500, color=(125, 50, 255)) cv2.imshow('canvas', canvas) cv2.waitKey(0) cv2.destroyAllWindows() ``` ![](https://img2020.cnblogs.com/blog/2161629/202011/2161629-20201129104621835-957722710.png) # 4. 綜合實驗-初始化背景 在這個綜合實驗裡會建立黑色背景、白色背景、彩色背景。 ``` ''' 初始化一個空白的畫布 並指定畫布的顏色 ''' import cv2 import numpy as np # 初始化一個空畫布 500×500 三通道 背景色為黑色 canvas_black = np.zeros((500, 500, 3), dtype="uint8") cv2.imshow("canvas_black", canvas_black) # 初始化一個空畫布 500×500 三通道 背景色為白色 canvas_white = np.ones((500, 500, 3), dtype="uint8") canvas_white *= 255 cv2.imshow("canvas_white", canvas_white) ''' 初始化一個彩色的畫布 - cv2版本 ''' 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 ''' 初始化終極版本 ''' def InitCanvasV3(width, height, color=(255, 255, 255)): canvas = np.ones((height, width, 3), dtype="uint8") canvas[:] = color return canvas # 初始化一個彩色的畫布 canvas_color = InitCanvasV2(500, 500, color=(100, 20, 50)) cv2.imshow("canvas_color", canvas_color) # 等待e鍵按下 關閉所有視窗 while cv2.waitKey(0) != ord('e'): continue cv2.destroyAllWindows() ``` ![](https://img2020.cnblogs.com/blog/2161629/202011/2161629-20201129104648666-379430078.png) # 資源傳送門 * 關注【**做一個柔情的程式猿**】公眾號 * 在【**做一個柔情的程式猿**】公眾號後臺回覆 【python資料】【2020秋招】 即可獲取相應的驚喜哦! # 「❤️ 感謝大家」 * 點贊支援下吧,讓更多的人也能看到這篇內容(收藏不點贊,都是耍流氓 -_-) * 歡迎在留言區與我分享你的想法,也歡迎你在留言區記錄你的思