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

歡迎訪問 生活随笔!

生活随笔

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

python

python opencv 图像切割_【OpenCV+Python】图像的基本操作与算术运算

發布時間:2023/12/4 python 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python opencv 图像切割_【OpenCV+Python】图像的基本操作与算术运算 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

圖像的基本操作

在上個教程中,我們介紹了使用鼠標畫筆的功能。本次教程,我們將要談及OpenCV圖像處理的基本操作。

本次教程的所有操作基本上都和Numpy相關,而不是與OpenCV相關。要使用OpenCV編寫更好的優化代碼,需要Numpy的豐富知識。

1.查看和修改像素值

我們要想查看一幅圖像中某一個像素點的像素值,首先需要進行定位,將其坐標標定,我們先來看一個彩色圖像(仍然是我們的貓咪,本次教程它是我們的主角):

現在我想查看某一個坐標的像素值,我們在pycharm中輸入代碼:

import?cv2import?numpy?as?npimg?=?cv2.imread("cat.jpg")#獲取像素值px?=?img[200,200]print(px)

代碼為查看圖像坐標(200,200)處的像素值,我們來看結果:

在之前的教程中我們談到,OpenCV對于圖像的讀取并非是RGB通道,而是BGR通道,那么程序輸出的[178,189,186]則分別對應于BGR的像素,我們可以進行驗證:

import?cv2import?numpy?as?npimg?=?cv2.imread("cat.jpg")#獲取像素值px?=?img[200,200]B?=?img[200,200,0]G = img[200,200,1]R?=?img[200,200,2]print(px,B,G,R)

現在我們假設,如果圖像并非彩色,而是黑白的灰度圖像,那么將會怎么輸出?先進行實驗:

我們仍然用剛剛的代碼進行實驗(前提是圖像已經灰度化處理,這在后面會講到),效果:

可以看到,BGR的像素一致,我們得出一個結論:對于灰度圖像,其輸出的像素值本質上為它的亮度強度值,值的范圍為0-255之間,當為0時,則全部為黑色,相反則為白色。

接下來我們來修改像素值,將指定坐標的像素值用一個數組進行賦值:

import?cv2import?numpy?as?npimg?=?cv2.imread("cat1.jpg")#獲取像素值px?=?img[200,200]print(px)img[200,200]?=?[225,225,225]print(img[200,200])

查看輸出:

可以看到,初始像素值跟修改之后的像素值。

一般來說,數組通常選擇的是某一片區域,比如頭幾行或者最后幾列。而對于某個像素點的訪問,Numpy數組方法,array.item() 和array.itemset()有著更好的作用。但是它返回的是一個標量。所以如果我們想訪問所有的B,G,R值,就需要分開調用array.item(),我們來看代碼(仍然以坐標200,200為例):

import?cv2import?numpy?as?npimg?=?cv2.imread("cat.jpg")#獲取像素值px?=?img[200,200]print(px)print(img.item(200,200,0))

我們用item輸出像素的B值,也就是藍色像素的數值:

實驗可以看到,跟之前的效果是一樣的。

對于指定坐標的賦值,我們使用itemset函數可以精確到某個像素,比如現在我只對藍色像素的數值進行改變:

import?cv2import?numpy?as?npimg?=?cv2.imread("cat.jpg")#獲取像素值px?=?img[200,200]print(px)print(img.item(200,200,0))img.itemset((200,200,0),100)print(img.item(200,200,0))

可以看到,對于指定的顏色通道的賦值時完全可以的。

2.查看圖像屬性

現在將要對圖像的各個屬性進行研究,圖像屬性包括行數、列數和通道數,圖像數據類型,像素數等。

對于一個圖像,我們使用shape可以返回行數、列數以及顏色通道的元數:

import?cv2import?numpy?as?npimg?=?cv2.imread("cat.jpg")print(img.shape)

輸出的第三個數值代表的是圖像的BGR三個通道的元數,也就是3。現在我們使用灰度圖像做實驗:

import?cv2import?numpy?as?npimg?=?cv2.imread("cat.jpg")img?=?cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)print(img.shape)

灰度圖像在之后的教程中會進行講解,這里先用做實驗:

可以看到,如果圖像是灰度的,則返回的元組僅包含行數和列數,因此這是檢查加載的圖像是灰度還是彩色的好方法。

通過size可以返回當前圖像的所有的像素點的總數:

import?cv2import?numpy?as?npimg?=?cv2.imread("cat.jpg")print(img.size)

圖像的數據類型可以通過dtype獲得:

import?cv2import?numpy?as?npimg?=?cv2.imread("cat.jpg")print(img.dtype)

imread函數默認讀取圖像的格式就是uint8,所以返回的全部都是這個格式。在以后我們學習深度學習框架時會發現,uint8的圖像數據格式用來進行模型訓練時,做數據歸一化(預處理階段)會導致精度缺失,最后導致分割精度下降。當然這是后話,我們現在不提。

如果我們想修改圖像的格式,我們需要用到astype函數,現在將圖像修改為float32格式的(這種格式的圖像被廣泛的應用于深度學習的模型訓練):

import?cv2import?numpy?as?npimg?=?cv2.imread("cat.jpg").astype(np.float32)print(img.dtype)

dtype在調試時非常重要,因為OpenCV-Python代碼中的大量錯誤是由無效的數據類型引起的,我們在以后的學習中會經常遇到這些問題。

3.圖像ROI

對于圖像中的特定區域的選取我們稱之為ROI,其實際上就是對圖像的xy坐標進行操作,我們來看示例:

import?cv2import?numpy?as?npimg?=?cv2.imread("cat.jpg")husky?=?img[1:240,60:270]cv2.imshow("img",husky)cv2.waitKey(0)cv2.destroyAllWindows()

本質相當于截取某一部分圖片,現在我們來做一些有意思的操作,將截取部分覆蓋到圖像的其他地方,本質相當于前面講過的像素修改:

import?cv2import?numpy?as?npimg?=?cv2.imread("cat.jpg")husky = img[1:240,60:270]img[61:300,270:480]?=?huskycv2.imshow("img",img)cv2.waitKey(0)cv2.destroyAllWindows()

4.分割和合并圖像通道

有時我們需要在B,G,R通道圖像上單獨進行操作。在這種情況下,需要將BGR圖像分割為單個通道。需要使用split函數與merge函數,它們的作用分別為分離和合并:

b,g,r = cv2.split(img) #拆分圖像通道img = cv2.merge((b,g,r))

此操作可以將BGR三通道分離出來,從而可以對某一通道進行操作,比如現在我們將R像素全部設置為0:

import?cv2import?numpy?as?npimg = cv2.imread("cat.jpg")b,g,r = cv2.split(img) #拆分圖像通道img[:,:,2] = 0r = img[:,:,2]img = cv2.merge((b,g,r))cv2.imshow("img",img)cv2.waitKey(0)cv2.destroyAllWindows()

r則為R通道,看效果:

將紅色通道去除后,我們的貓咪變的有點綠了。當然,大家還可以進行其他的通道的實驗。

5.圖像邊框填充

如果要在圖像周圍創建邊框(如相框),則可以使用函數cv2.copyMakeBorder()。它在卷積運算(很重要),零填充等方面有更多應用。

此函數采用以下參數:

cv2.copyMakeBorder(src, top, bottom, left, right, borderType[, dst[, value]])

? src—輸入圖像

? top,bottom,left,right—相應方向上像素數的邊框寬度

? value—cv2.BORDER_CONSTANT,cv2.BORDER_REFLECT,cv2.BORDER_REFLECT_101 or cv2.BORDER_DEFAULT ,cv2.BORDER_REPLICATE,cv2.BORDER_WRAP

cv2.BORDER_REFLECT_101或cv2.BORDER_DEFAULT

? 與上面相同,但略有改動,如下所示:gfedcb | abcdefgh | gfedcba

cv.BORDER_REPLICATE

? 最后一個像素在整個過程中被復制,像:aaaaaa |abcdefgh|hhhhhhh這樣

cv.BORDER_WRAP

? 對稱方向 像素互換 就像:cdefgh|abcdefgh|abcdefg 這樣。

我們來看代碼:

import?cv2from?matplotlib?import?pyplot?as?pltBLUE?=?[255,0,0]img1?=?cv2.imread('cat.jpg')replicate?=?cv2.copyMakeBorder(img1,10,10,10,10,cv2.BORDER_REPLICATE)reflect?=?cv2.copyMakeBorder(img1,10,10,10,10,cv2.BORDER_REFLECT)reflect101?=?cv2.copyMakeBorder(img1,10,10,10,10,cv2.BORDER_REFLECT_101)wrap?=?cv2.copyMakeBorder(img1,10,10,10,10,cv2.BORDER_WRAP)constant=?cv2.copyMakeBorder(img1,10,10,10,10,cv2.BORDER_CONSTANT,value=BLUE)plt.subplot(231),plt.imshow(img1,'gray'),plt.title('ORIGINAL')plt.subplot(232),plt.imshow(replicate,'gray'),plt.title('REPLICATE')plt.subplot(233),plt.imshow(reflect,'gray'),plt.title('REFLECT')plt.subplot(234),plt.imshow(reflect101,'gray'),plt.title('REFLECT_101')plt.subplot(235),plt.imshow(wrap,'gray'),plt.title('WRAP')plt.subplot(236),plt.imshow(constant,'gray'),plt.title('CONSTANT')plt.show()


實驗效果:

對于五個參數都進行了實驗,可以看到明顯的不同,當然,在這里為了方便圖片對比顯示,我們使用了matplotlib庫,不過這屬于python的知識,在這里就不一一介紹講解了,大家也可以修改代碼用OpenCV進行其他參數輸出。

圖像的算術運算

本次教程我們將概述圖像的算數運算,眾所周知,數學中有著加減乘除運算,同樣的,圖像也是如此,它的本質實際上就是一個矩陣,所以圖像也存在著加法、減法、位運算等等算數運算。

1.加法

使用cv2.add()將兩個圖像相加,可以使用numpy中的矩陣加法來實現。但是在opencv中加法是飽和操作,也就是有上限值,numpy會對結果取模,綜上,使用opencv的效果更好,我們來看函數實例:

cv2.add(img1, img2) # 進行圖片的加和


參數說明:cv2.add將兩個圖片進行加和,大于255的使用255計數。

我們將使用以下兩個圖片作為實例:

來看代碼:

import cv2img1 = cv2.imread("01.jpg")img2 = cv2.imread("02.jpg")res = cv2.add(img1,img2)cv2.imshow("res",res)cv2.waitKey(0)cv2.destroyAllWindows()

不難理解,第一幅圖像白色部分像素部分為255,黑色部分像素為0,所以和第二幅圖像加起來之后白色部分仍然是白色部分,因為加起來的值大于255時,默認取值255。

2.減法

減法運算就是兩幅圖像見對象像素的灰度值或彩色分量進行相減,它可以用于目標檢測,需要用到函數cv2.subtract(),程序實現:

import?cv2img1?=?cv2.imread("01.jpg")img2?=?cv2.imread("02.jpg")res?=?cv2.subtract(img1,img2)cv2.imshow("res",res)cv2.waitKey(0)cv2.destroyAllWindows()

3.乘法

圖像的乘法運算就是將兩幅圖像對應的灰度值或彩色分量進行相乘。

乘運算的主要作用是抑制圖像的某些區域,掩膜值置為1,否則置為0。乘運算有時也被用來實現卷積或相關的運算,其相關函數為cv2.multiply()。

以下為相關程序代碼:

import?cv2img1?=?cv2.imread("01.jpg")img2?=?cv2.imread("02.jpg")res?=?cv2.multiply(img1,img2)cv2.imshow("res",res)cv2.waitKey(0)cv2.destroyAllWindows()

4.除法

圖像除運算就是兩幅圖像對應像素的灰度值或彩色分量進行相除。簡單的出運算可以用于改變圖像的灰度級。其相關函數為cv2.divide。

以下為代碼部分:

5.圖像融合

它實際上本質也是一個加法運算,但是這個加法運算跟普通的并不一樣,我們可以理解為是一種加權的運算。

我們用函數來表示一個圖像,前提是所有的圖像尺寸是一樣的,即圖像矩陣的行列一樣,通道數一樣。

我們用 f0(x) 和 f1(x) 來表示輸入的圖像,用 g(x) 來表示輸出圖像,α表示比例( 0≤α≤1 ,一般來說,α取0和1沒有太大意義),那我們能得到如下圖所示的一個公式:

所以圖像混合就是將兩個圖像按照一定的比例轉存到另一個圖像中。

首先需要看一下函數原型:

cv2.addWeighted(src1, alpha, src2, beta, gamma[, dst[, dtype]]) → dst

? src1—第一個輸入數組。

? alpha—第一個數組元素的權重。

? src2—第二個輸入數組,其大小和通道號與src1相同。

? beta—第二個數組元素的權重。

? gamma—標量加到每個和。

? dst—輸出數組,其大小和通道數與輸入數組相同。

? dtype—輸出數組的可選深度;當兩個輸入數組的深度相同時,可以將dtype設置為-1,這等效于src1.depth()。

此函數可以用以下矩陣表達式進行代替:

dst = src1 * alpha + src2 * beta + gamma;

注意:由參數說明可以看出,被疊加的兩幅圖像必須是尺寸相同、類型相同的;并且,當輸出圖像array的深度為CV_32S時,這個函數就不適用了,這時候就會內存溢出或者算出的結果壓根不對。

我們來看一下代碼:

import?cv2img1?=?cv2.imread("01.jpg")img?=?cv2.imread("02.jpg")h,?w,?_?=?img1.shapeimg2?=?cv2.resize(img,?(w,h),?interpolation=cv2.INTER_AREA)alpha?=?0.7beta?=?1-alphagamma = 0img_add?=?cv2.addWeighted(img1,?alpha,?img2,?beta,?gamma)cv2.imshow('img_add',img_add)cv2.waitKey()cv2.destroyAllWindows()

效果:

此函數最大的缺陷就是需要兩張圖片尺寸必須完全一樣,所以在實驗時必須要注意。

6.按位運算

我們在學習數電時想必都學過邏輯運算,OpenCV中也有相關的運算。與或非這些想必就不必再多講了,我們可以通過代碼實驗來熟悉:

1)與運算:

import?cv2img1?=?cv2.imread("01.jpg")img2?=?cv2.imread("02.jpg")res?=?cv2.bitwise_and(img1,img2)cv2.imshow("res",res)cv2.waitKey()cv2.destroyAllWindows()

2)或運算:

import?cv2img1?=?cv2.imread("01.jpg")img2?=?cv2.imread("02.jpg")res?=?cv2.bitwise_or(img1,img2)cv2.imshow("res",res)cv2.waitKey()cv2.destroyAllWindows()

可以看到,跟加法運算基本上類似。

3)非運算:

import?cv2img1?=?cv2.imread("01.jpg")img2?=?cv2.imread("02.jpg")res?=?cv2.bitwise_not(img1,img2)cv2.imshow("res",res)cv2.waitKey()cv2.destroyAllWindows()

非運算在之后的學習中是非常有幫助的,它的以用來對二值化圖像進行取反,然后方便進行形態學操作。

4)異或運算:

import cv2img1?=?cv2.imread("01.jpg")img2?=?cv2.imread("02.jpg")res?=?cv2.bitwise_xor(img1,img2)cv2.imshow("res",res)cv2.waitKey()cv2.destroyAllWindows()

關于圖像的所有的基本運算就介紹到這里。

7.練習實例

現在帶大家做一個好玩的小項目,題目是:用OpenCV完成一個幻燈片演示一幅圖轉成另一幅圖,并在圖像之間進行平滑過渡。

實際上,我們使用剛剛的線性加權函數就可以完成,我們只需要定義一個變量a,然后讓其值小于一,變量的值依次遞增。這樣總體進行分析的話,第一幅圖圖像的加權值為a,第二幅圖像的加權值為1-a,那么在一個循環里面它們會進行動態過渡,我們來看一下代碼:

import?cv2?as?cvimg1?=?cv.imread('01.jpg')img2 = cv.imread('02.jpg')l, h = img1.shape[0:2]img2_R = cv.resize(img2, (h, l))a=0cv.namedWindow('ppt',True)dst = cv.addWeighted(img1, a, img2_R, 1-a, -1)cv.imshow('ppt', dst)cv.waitKey(0)while a<1.0:dst = cv.addWeighted(img1, a, img2_R, 1-a, -1)cv.imshow('ppt', dst)cv.waitKey(100)a+=0.02cv.waitKey(0)cv.destroyAllWindows()

按下esc鍵開始幻燈片放映,由于效果為動態,此處不便展示,大家請自己實驗,還是很有意思的。

掃碼入群掃碼添加管理員微信

加入“電子產品世界”粉絲交流群

↓↓↓↓點擊,查看更多新聞

總結

以上是生活随笔為你收集整理的python opencv 图像切割_【OpenCV+Python】图像的基本操作与算术运算的全部內容,希望文章能夠幫你解決所遇到的問題。

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