日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

OpenCV之Python学习笔记(1)(2): 图像的载入、显示和保存 图像元素的访问、通道分离与合并

發布時間:2025/3/21 python 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 OpenCV之Python学习笔记(1)(2): 图像的载入、显示和保存 图像元素的访问、通道分离与合并 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

OpenCV之Python學習筆記

一直都在用Python+OpenCV做一些算法的原型。本來想留下發布一些文章的,可是整理一下就有點無奈了,都是寫零散不成系統的小片段。現在看到一本國外的新書《OpenCV Computer Vision with Python》,于是就看一遍,順便把自己掌握的東西整合一下,寫成學習筆記了。更需要的朋友參考。

閱讀須知:

??????? 本文不是純粹的譯文,只是比較貼近原文的筆記;
??????? 請設法購買到出版社出版的書,支持正版。

?????? 從書名就能看出來本書是介紹在Python中使用OpenCV,全書分為5章,兩個附錄:

  • 第一章OpenCV設置,介紹如何在Windows、Mac和Ubuntu上設置Pyhton、OpenCV和相關庫的環境。還討論了OpenCV社區、OpenCV文檔以及官方的示例代碼。
  • 第二章處理文件、攝像頭和GUI,討論OpenCV的I/O功能,接著使用面向對象的設計編寫一個主應用程序,用于顯示攝像頭實時場景、處理鍵盤輸入、將攝像頭寫入視頻文件和靜態圖像文件。
  • 第三章圖像過濾,介紹使用OpenCV、NumPy和SciPy來編寫圖像過濾器。過濾器可用于線性顏色操作、曲線顏色操作、模糊化、銳化和尋找邊緣。本章修改第一章的主程序,將過濾器應用到實時攝像頭場景中。
  • 第四章使用Haar Cascades追蹤人臉,本章將編寫一個層次化的人臉追蹤器,使用OpenCV定位圖像中的臉部、眼睛、鼻子和嘴巴。同時還編寫了用于復制和改變圖像中某塊區域的大小。同樣,本章也將修改之前的主應用程序,讓其可以用于找到并處理攝像頭場景中的人臉。
  • 第五章檢測前景/背景區域和深度。通過本章將了解有關OpenCV(在OpenNI和SensorKinect的支持下)從深度攝像頭中獲得的數據類型的信息。接著編寫一些函數,使用這些數據對前景區域施加一些限制效果。最后將這些函數整合到主程序中,使得在處理人臉之前先進行細化操作。
  • 附錄A,與Pygame整合。修改主程序,用Pygame替換OpenCV來處理特定的I/O事件。(Pygame提供了更多樣的事件處理函數。)
  • 附錄B,為自定義目標生成Haar Cascades,允許我們檢測一系列的OpenCV工具,來對任何類型的目標或模式構建跟蹤器,而不僅僅是人臉。

本書第一章是介紹在不同操作系統上對OpenCV、Python及相關庫的配置,這里就不介紹了。下一篇文章將直接從第二章開始介紹。






OpenCV Python教程(1、圖像的載入、顯示和保存)


本文是OpenCV? 2 Computer Vision Application Programming Cookbook讀書筆記的第一篇。在筆記中將以Python語言改寫每章的代碼。

PythonOpenCV的配置這里就不介紹了。

注意,現在OpenCV for Python就是通過NumPy進行綁定的。所以在使用時必須掌握一些NumPy的相關知識!

圖像就是一個矩陣,在OpenCV for Python中,圖像就是NumPy中的數組!

如果讀取圖像首先要導入OpenCV包,方法為:

[python]?view plaincopy
  • import?cv2??
  • 讀取并顯示圖像

    在Python中不需要聲明變量,所以也就不需要C++中的cv::Mat xxxxx了。只需這樣:

    [python]?view plaincopy
  • img?=?cv2.imread("D:\cat.jpg")??
  • OpenCV目前支持讀取bmp、jpg、png、tiff等常用格式。更詳細的請參考OpenCV的參考文檔。

    接著創建一個窗口

    [python]?view plaincopy
  • cv2.namedWindow("Image")??
  • 然后在窗口中顯示圖像

    [python]?view plaincopy
  • cv2.imshow("Image",?img)??
  • 最后還要添上一句:

    [python]?view plaincopy
  • cv2.waitKey?(0)??
  • 如果不添最后一句,在IDLE中執行窗口直接無響應。在命令行中執行的話,則是一閃而過。

    完整的程序為:

    [python]?view plaincopy
  • import?cv2???
  • ??
  • img?=?cv2.imread("D:\\cat.jpg")???
  • cv2.namedWindow("Image")???
  • cv2.imshow("Image",?img)???
  • cv2.waitKey?(0)??
  • cv2.destroyAllWindows()??
  • 最后釋放窗口是個好習慣!

    創建/復制圖像


    新的OpenCV的接口中沒有CreateImage接口。即沒有cv2.CreateImage這樣的函數。如果要創建圖像,需要使用numpy的函數(現在使用OpenCV-Python綁定,numpy是必裝的)。如下:

    [python]?view plaincopy
  • emptyImage?=?np.zeros(img.shape,?np.uint8)??
  • 在新的OpenCV-Python綁定中,圖像使用NumPy數組的屬性來表示圖像的尺寸和通道信息。如果輸出img.shape,將得到(500, 375, 3),這里是以OpenCV自帶的cat.jpg為示例。最后的3表示這是一個RGB圖像。

    也可以復制原有的圖像來獲得一副新圖像。

    [python]?view plaincopy
  • emptyImage2?=?img.copy();??
  • 如果不怕麻煩,還可以用cvtColor獲得原圖像的副本。 [python]?view plaincopy
  • emptyImage3=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)??
  • #emptyImage3[...]=0??
  • 后面的emptyImage3[...]=0是將其轉成空白的黑色圖像。

    保存圖像?

    保存圖像很簡單,直接用cv2.imwrite即可。

    cv2.imwrite("D:\\cat2.jpg", img)

    第一個參數是保存的路徑及文件名,第二個是圖像矩陣。其中,imwrite()有個可選的第三個參數,如下:

    cv2.imwrite("D:\\cat2.jpg", img,[int(cv2.IMWRITE_JPEG_QUALITY), 5])

    第三個參數針對特定的格式: 對于JPEG,其表示的是圖像的質量,用0-100的整數表示,默認為95。 注意,cv2.IMWRITE_JPEG_QUALITY類型為Long,必須轉換成int。下面是以不同質量存儲的兩幅圖:

    對于PNG,第三個參數表示的是壓縮級別。cv2.IMWRITE_PNG_COMPRESSION,從0到9,壓縮級別越高,圖像尺寸越小。默認級別為3:

    [python]?view plaincopy
  • cv2.imwrite("./cat.png",?img,?[int(cv2.IMWRITE_PNG_COMPRESSION),?0])???
  • cv2.imwrite("./cat2.png",?img,?[int(cv2.IMWRITE_PNG_COMPRESSION),?9])??
  • 保存的圖像尺寸如下:

    還有一種支持的圖像,一般不常用。

    完整的代碼為:

    [python]?view plaincopy
  • import?cv2??
  • import?numpy?as?np??
  • ??
  • img?=?cv2.imread("./cat.jpg")??
  • emptyImage?=?np.zeros(img.shape,?np.uint8)??
  • ??
  • emptyImage2?=?img.copy()??
  • ??
  • emptyImage3=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)??
  • #emptyImage3[...]=0??
  • ??
  • cv2.imshow("EmptyImage",?emptyImage)??
  • cv2.imshow("Image",?img)??
  • cv2.imshow("EmptyImage2",?emptyImage2)??
  • cv2.imshow("EmptyImage3",?emptyImage3)??
  • cv2.imwrite("./cat2.jpg",?img,?[int(cv2.IMWRITE_JPEG_QUALITY),?5])??
  • cv2.imwrite("./cat3.jpg",?img,?[int(cv2.IMWRITE_JPEG_QUALITY),?100])??
  • cv2.imwrite("./cat.png",?img,?[int(cv2.IMWRITE_PNG_COMPRESSION),?0])??
  • cv2.imwrite("./cat2.png",?img,?[int(cv2.IMWRITE_PNG_COMPRESSION),?9])??
  • cv2.waitKey?(0)??
  • cv2.destroyAllWindows()??

  • 參考資料:
    《OpenCV References Manuel》
    《OpenCV? 2 Computer Vision Application Programming Cookbook》
    《OpenCV Computer Vision with Python》




    OpenCV Python教程(2、圖像元素的訪問、通道分離與合并)


    OpenCV Python教程之圖像元素的訪問、通道分離與合并

    轉載請詳細注明原作者及出處,謝謝!

    訪問像素

    像素的訪問和訪問numpy中ndarray的方法完全一樣,灰度圖為:

    [python]?view plaincopy
  • img[j,i]?=?255??
  • 其中j,i分別表示圖像的行和列。對于BGR圖像,為: [python]?view plaincopy
  • img[j,i,0]=?255??
  • img[j,i,1]=?255??
  • img[j,i,2]=?255??
  • 第三個數表示通道。

    下面通過對圖像添加人工的椒鹽現象來進一步說明OpenCV?Python中需要注意的一些問題。完整代碼如下:

    [python]?view plaincopy
  • import?cv2??
  • import?numpy?as?np??
  • ??
  • def?salt(img,?n):??
  • ????for?k?in?range(n):??
  • ????????i?=?int(np.random.random()?*?img.shape[1]);??
  • ????????j?=?int(np.random.random()?*?img.shape[0]);??
  • ????????if?img.ndim?==?2:???
  • ????????????img[j,i]?=?255??
  • ????????elif?img.ndim?==?3:???
  • ????????????img[j,i,0]=?255??
  • ????????????img[j,i,1]=?255??
  • ????????????img[j,i,2]=?255??
  • ????return?img??
  • ??
  • if?__name__?==?'__main__':??
  • ????img?=?cv2.imread("圖像路徑")??
  • ????saltImage?=?salt(img,?500)??
  • ????cv2.imshow("Salt",?saltImage)??
  • ????cv2.waitKey(0)??
  • ????cv2.destroyAllWindows()??
  • 處理后能得到類似下面這樣帶有模擬椒鹽現象的圖片:



    上面的代碼需要注意幾點:

    1、與C++不同,在Python中灰度圖的img.ndim = 2,而C++中灰度圖圖像的通道數img.channel() =1

    2、為什么使用np.random.random()?
    這里使用了numpy的隨機數,Python自身也有一個隨機數生成函數。這里只是一種習慣,np.random模塊中擁有更多的方法,而Python自帶的random只是一個輕量級的模塊。不過需要注意的是np.random.seed()不是線程安全的,而Python自帶的random.seed()是線程安全的。如果使用隨機數時需要用到多線程,建議使用Python自帶的random()和random.seed(),或者構建一個本地的np.random.Random類的實例。

    分離、合并通道

    由于OpenCV Python和NumPy結合的很緊,所以即可以使用OpenCV自帶的split函數,也可以直接操作numpy數組來分離通道。直接法為:

    [python]?view plaincopy
  • import?cv2??
  • import?numpy?as?np??
  • ??
  • img?=?cv2.imread("D:/cat.jpg")??
  • b,?g,?r?=?cv2.split(img)??
  • cv2.imshow("Blue",?r)??
  • cv2.imshow("Red",?g)??
  • cv2.imshow("Green",?b)??
  • cv2.waitKey(0)??
  • cv2.destroyAllWindows()??
  • 其中split返回RGB三個通道,如果只想返回其中一個通道,可以這樣: [python]?view plaincopy
  • b?=?cv2.split(img)[0]??
  • g?=?cv2.split(img)[1]??
  • r?=?cv2.split(img)[2]??
  • 最后的索引指出所需要的通道。

    也可以直接操作NumPy數組來達到這一目的:

    [python]?view plaincopy
  • import?cv2??
  • import?numpy?as?np??
  • ??
  • img?=?cv2.imread("D:/cat.jpg")??
  • ??
  • b?=?np.zeros((img.shape[0],img.shape[1]),?dtype=img.dtype)??
  • g?=?np.zeros((img.shape[0],img.shape[1]),?dtype=img.dtype)??
  • r?=?np.zeros((img.shape[0],img.shape[1]),?dtype=img.dtype)??
  • ??
  • b[:,:]?=?img[:,:,0]??
  • g[:,:]?=?img[:,:,1]??
  • r[:,:]?=?img[:,:,2]??
  • ??
  • cv2.imshow("Blue",?r)??
  • cv2.imshow("Red",?g)??
  • cv2.imshow("Green",?b)??
  • cv2.waitKey(0)??
  • cv2.destroyAllWindows()??
  • 注意先要開辟一個相同大小的圖片出來。這是由于numpy中數組的復制有些需要注意的地方,具體事例如下: [python]?view plaincopy
  • >>>?c=?np.zeros(img.shape,?dtype=img.dtype)??
  • >>>?c[:,:,:]?=?img[:,:,:]??
  • >>>?d[:,:,:]?=?img[:,:,:]??
  • >>>?c?is?a??
  • False??
  • >>>?d?is?a??
  • False??
  • >>>?c.base?is?a??
  • False??
  • >>>?d.base?is?a?#注意這里!!!??
  • True??
  • 這里,d只是a的鏡像,具體請參考《 NumPy簡明教程(二,數組3 )》中的“復制和鏡像”一節。

    通道合并

    同樣,通道合并也有兩種方法。第一種是OpenCV自帶的merge函數,如下:

    [python]?view plaincopy
  • merged?=?cv2.merge([b,g,r])?#前面分離出來的三個通道??
  • 接著是NumPy的方法: [python]?view plaincopy
  • mergedByNp?=?np.dstack([b,g,r])???
  • 注意:這里只是演示,實際使用時請用OpenCV自帶的merge函數! 用NumPy組合的結果不能在OpenCV中其他函數使用,因為其組合方式與OpenCV自帶的不一樣,如下: [python]?view plaincopy
  • merged?=?cv2.merge([b,g,r])??
  • print?"Merge?by?OpenCV"???
  • print?merged.strides??
  • ??
  • mergedByNp?=?np.dstack([b,g,r])???
  • print?"Merge?by?NumPy?"???
  • print?mergedByNp.strides??
  • 結果為: [python]?view plaincopy
  • Merge?by?OpenCV??
  • (1125,?3,?1)??
  • Merge?by?NumPy??
  • (1,?500,?187500)??
  • NumPy數組的strides屬性表示的是在每個維數上以字節計算的步長。這怎么理解呢,看下面這個簡單點的例子: [python]?view plaincopy
  • >>>?a?=?np.arange(6)??
  • >>>?a??
  • array([0,?1,?2,?3,?4,?5])??
  • >>>?a.strides??
  • (4,)??
  • a數組中每個元素都是NumPy中的整數類型,占4個字節,所以第一維中相鄰元素之間的步長為4(個字節)。

    同樣,2維數組如下:

    [python]?view plaincopy
  • >>>?b?=?np.arange(12).reshape(3,4)??
  • >>>?b??
  • array([[?0,??1,??2,??3],??
  • ???????[?4,??5,??6,??7],??
  • ???????[?8,??9,?10,?11]])??
  • >>>?b.strides??
  • (16,?4)??
  • 從里面開始看,里面是一個4個元素的一維整數數組,所以步長應該為4。外面是一個含有3個元素,每個元素的長度是4×4=16。所以步長為16。

    下面來看下3維數組:

    [python]?view plaincopy
  • >>>?c?=?np.arange(27).reshape(3,3,3)??
  • 其結果為: [python]?view plaincopy
  • array([[[?0,??1,??2],??
  • ????????[?3,??4,??5],??
  • ????????[?6,??7,??8]],??
  • ??
  • ???????[[?9,?10,?11],??
  • ????????[12,?13,?14],??
  • ????????[15,?16,?17]],??
  • ??
  • ???????[[18,?19,?20],??
  • ????????[21,?22,?23],??
  • ????????[24,?25,?26]]])??
  • 根據前面了解的,推斷下這個數組的步長。從里面開始算,應該為(3×4×3,3×4,4)。驗證一下: [python]?view plaincopy
  • >>>?c.strides??
  • (36,?12,?4)??
  • 完整的代碼為: [python]?view plaincopy
  • import?cv2??
  • import?numpy?as?np??
  • ??
  • img?=?cv2.imread("D:/cat.jpg")??
  • ??
  • b?=?np.zeros((img.shape[0],img.shape[1]),?dtype=img.dtype)??
  • g?=?np.zeros((img.shape[0],img.shape[1]),?dtype=img.dtype)??
  • r?=?np.zeros((img.shape[0],img.shape[1]),?dtype=img.dtype)??
  • ??
  • b[:,:]?=?img[:,:,0]??
  • g[:,:]?=?img[:,:,1]??
  • r[:,:]?=?img[:,:,2]??
  • ??
  • merged?=?cv2.merge([b,g,r])??
  • print?"Merge?by?OpenCV"???
  • print?merged.strides??
  • print?merged??
  • ??
  • mergedByNp?=?np.dstack([b,g,r])???
  • print?"Merge?by?NumPy?"???
  • print?mergedByNp.strides??
  • print?mergedByNp??
  • ??
  • cv2.imshow("Merged",?merged)??
  • cv2.imshow("MergedByNp",?merged)??
  • cv2.imshow("Blue",?b)??
  • cv2.imshow("Red",?r)??
  • cv2.imshow("Green",?g)??
  • cv2.waitKey(0)??
  • cv2.destroyAllWindows() ?


  • from: http://blog.csdn.net/sunny2038/article/category/904451

    總結

    以上是生活随笔為你收集整理的OpenCV之Python学习笔记(1)(2): 图像的载入、显示和保存 图像元素的访问、通道分离与合并的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。