內(nèi)核中讀寫文件
公司專注于為企業(yè)提供網(wǎng)站制作、成都網(wǎng)站設(shè)計(jì)、微信公眾號(hào)開發(fā)、商城網(wǎng)站制作,成都小程序開發(fā),軟件定制網(wǎng)站設(shè)計(jì)等一站式互聯(lián)網(wǎng)企業(yè)服務(wù)。憑借多年豐富的經(jīng)驗(yàn),我們會(huì)仔細(xì)了解各客戶的需求而做出多方面的分析、設(shè)計(jì)、整合,為客戶設(shè)計(jì)出具風(fēng)格及創(chuàng)意性的商業(yè)解決方案,成都創(chuàng)新互聯(lián)更提供一系列網(wǎng)站制作和網(wǎng)站推廣的服務(wù)。
1.filp_open()在kernel中可以打開文件,其原形如下:
Struct file* filp_open(const char* filename, int open_mode, int mode); 該函數(shù)返回strcut file*結(jié)構(gòu)指針,供后繼函數(shù)操作使用,該返回值用IS_ERR()來檢驗(yàn)其有效性。
2. 讀寫文件(vfs_read/vfs_write)
kernel中文件的讀寫操作可以使用vfs_read()和vfs_write,在使用這兩個(gè)函數(shù)前需要說明一下get_fs()和 set_fs()這兩個(gè)函數(shù)。
vfs_read() vfs_write()兩函數(shù)的原形如下:
ssize_t vfs_read(struct file* filp, char __user* buffer, size_t len, loff_t* pos);
ssize_t vfs_write(struct file* filp, const char __user* buffer, size_t len, loff_t* pos);
注意這兩個(gè)函數(shù)的第二個(gè)參數(shù)buffer,前面都有__user修飾符,這就要求這兩個(gè)buffer指針都應(yīng)該指向用空的內(nèi)存,如果對(duì)該參數(shù)傳遞kernel空間的指針,這兩個(gè)函數(shù)都會(huì)返回失敗-EFAULT。但在Kernel中,我們一般不容易生成用戶空間的指針,或者不方便獨(dú)立使用用戶空間內(nèi)存。要使這兩個(gè)讀寫函數(shù)使用kernel空間的buffer指針也能正確工作,需要使用set_fs()函數(shù)或宏(set_fs()可能是宏定義),如果為函數(shù),其原形如下:
void set_fs(mm_segment_t fs);
該函數(shù)的作用是改變kernel對(duì)內(nèi)存地址檢查的處理方式,其實(shí)該函數(shù)的參數(shù)fs只有兩個(gè)取值:USER_DS,KERNEL_DS,分別代表用戶空間和內(nèi)核空間,默認(rèn)情況下,kernel取值為USER_DS,即對(duì)用戶空間地址檢查并做變換。那么要在這種對(duì)內(nèi)存地址做檢查變換的函數(shù)中使用內(nèi)核空間地址,就需要使用set_fs(KERNEL_DS)進(jìn)行設(shè)置。get_fs()一般也可能是宏定義,它的作用是取得當(dāng)前的設(shè)置,這兩個(gè)函數(shù)的一般用法為:
Mat類:
是用于保存圖像以及其他矩陣數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)。
圖像載入函數(shù)imread():
Mat imread(const string filename, int flags=1);
filename表示圖像載入的路徑;
flags為載入標(biāo)識(shí)。
flags=0 將圖像轉(zhuǎn)換為灰度再返回;
flags=1 將圖像轉(zhuǎn)換成彩色再返回;
flags=2 若載入圖像的深度是16位或者32位,就返回對(duì)應(yīng)的圖像深度,否則,將圖像轉(zhuǎn)換為8位圖像再返回。
flags=2|4 載入最真實(shí)無損的源圖像
若flags不在枚舉類型當(dāng)中,flags0 返回一個(gè)三通道的彩色圖像;flags=0 返回灰度圖像;flags0 返回包含Alpha通道的加載圖像。
圖像顯示函數(shù)imshow():
void imshow(const string winname, InputArray mat);
winname填寫要顯示的窗口標(biāo)識(shí)名稱;
mat填需要顯示的圖像。
輸出圖像到文件imwrite():
bool imwrite(const string filename, InputArray img, const vector params=vector());
第一個(gè)參數(shù)filename表示要寫入的文件名
第二個(gè)參數(shù)img表示Mat類型的圖像數(shù)據(jù)
通道分離split()函數(shù);
void split(const Mat src, Mat* mvbegin);
void split(InputArray m, OutputArrayofArray mv);
第一個(gè)參數(shù)表示需要進(jìn)行分離的多通道數(shù)組;
第二個(gè)參數(shù)表示函數(shù) 輸出數(shù)組或輸出的vector容器。
通道合并merge()函數(shù):
void merge(const Mat* mv, size_t count, OutputArray dst)
void merge(InputArrayOfArray mv, OutputArray dst);
第一個(gè)參數(shù)mv表示需要被合并的輸入矩陣或vector容器的陣列,mv參數(shù)中所有矩陣必須擁有一樣的尺寸;
第二個(gè)參數(shù)count表示當(dāng)mv為空白的C數(shù)組時(shí),代表輸入矩陣的個(gè)數(shù),通常可以省略不寫;
第三個(gè)參數(shù)dst表示輸出矩陣,和mv擁有一樣的尺寸和深度
Python與OpenCV圖像簡(jiǎn)單操作
文章目錄
OpenCV安裝
1.讀取圖片
2.保存圖片
3.截取部分圖像
4.圖片翻轉(zhuǎn)
5.縮放圖片
6.轉(zhuǎn)換為灰度圖像
7.在一個(gè)窗口中顯示兩張圖片
8.繪圖功能
OpenCV安裝
打開命令行輸入 pip install opencv-python(前提是有python環(huán)境)
1.讀取圖片
使用 cv2.imread() 函數(shù),給出了幾種讀取圖片路徑的寫法
import cv2#導(dǎo)入opencv包
#python中不需要聲明變量
img1 = cv2.imread("D:/test/1.jpg")#絕對(duì)路徑,推薦
img2 = cv2.imread("D:\\test\\2.jpg")#通常是兩個(gè)斜線,單右斜線會(huì)被當(dāng)成轉(zhuǎn)義符
img3 = cv2.imread("3.jpeg")#相對(duì)路徑,將圖片放在py文件對(duì)應(yīng)目錄下
cv2.imshow("test1", img1)
cv2.imshow("test2", img2)
cv2.imshow("test3", img3)
cv2.waitKey(0)#沒有這一句圖片會(huì)一閃而過
##waitkey(delay=0),等待用戶輸入按鍵,返回該按鍵的值
2.保存圖片
使用 cv2.write() 函數(shù)保存圖片
import cv2# 導(dǎo)入OpenCV包
img=cv2.imread("D:/test/3.png",cv2.IMREAD_COLOR)
cv2.imshow("test",img)#OpenCV可以實(shí)現(xiàn)不同格式圖片轉(zhuǎn)換,支持jpg、bmp、png等圖片格式相互無損轉(zhuǎn)換
cv2.imwrite("D:/test/3.1.png",img)#將改變后的圖像保存
cv2.imwrite("D:/test/3.2.bmp",img)
cv2.waitKey(0)
3.截取部分圖像
import cv2
img = cv2.imread("D:\\test\\2.jpg")
frame = img[200:400,200:400] #截取部分圖像,200-400行,200-400列
cv2.imshow("test",frame)#顯示截取后的圖像
cv2.waitKey(0)
4.圖片翻轉(zhuǎn)
使用cv2.flip(img,flipcode)來進(jìn)行圖片翻轉(zhuǎn)
flipcode控制圖片翻轉(zhuǎn)方向
import cv2
img=cv2.imread("D:/test/5.jpg",cv2.IMREAD_COLOR)
flipCode1=1#大于0左右翻轉(zhuǎn)
flipCode2=0#等于0上下翻轉(zhuǎn)
flipCode3=-1#小于0先上下翻轉(zhuǎn)再左右翻轉(zhuǎn)
img1 = cv2.flip(img, flipCode1)#filpCode控制圖片翻轉(zhuǎn)方向
img2 = cv2.flip(img, flipCode2)
img3 = cv2.flip(img, flipCode3)
cv2.imshow("test",img)
cv2.imshow("test1",img1)
cv2.imshow("test2",img2)
cv2.imshow("test3",img3)
cv2.waitKey(0)
5.縮放圖片
cv2.resize(img,dsize,fx,fy),dsize和fx,fy都可以設(shè)置圖片大小,不能同時(shí)為0
import cv2# 導(dǎo)入OpenCV包
img = cv2.imread("D:/test/2.jpg",cv2.IMREAD_COLOR)
img1 = cv2.resize(img, (700, 700))#設(shè)置輸出圖片的尺寸
img2 = cv2.resize(img, None, fx=0.7, fy=0.7)#None的位置本來是輸出圖片的尺寸,這里設(shè)置了縮放因子
#fx-水平軸上的比例因子,fy-垂直軸上的比例因子
cv2.imshow("test", img)
cv2.imshow("test1", img1)
cv2.imshow("test2", img2)
cv2.imwrite("D:/test/resize.jpg", img1)# 保存圖像
cv2.waitKey(0)
6.轉(zhuǎn)換為灰度圖像
cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
cv2.COLOR_RGB2GRAY表示把RGB圖像轉(zhuǎn)為灰度圖像,2前是轉(zhuǎn)換前,2后是轉(zhuǎn)換后
import cv2#導(dǎo)入opencv包
#python中不需要聲明變量
img = cv2.imread("D:/test/1.jpg")#cv2.imread讀進(jìn)來的圖片格式是BGR(W,H,C),而不是RGB
cv2.imshow("BGR", img)
#將圖像轉(zhuǎn)換為RGB格式
img1 = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)#因?yàn)閛pencv讀取圖片是按BGR讀的,所以轉(zhuǎn)換為RGB反而不像原圖
cv2.imshow("RGB",img1)
#將圖像轉(zhuǎn)換為灰度圖像
img2 = cv2.cvtColor(img1, cv2.COLOR_RGB2GRAY)
cv2.imshow("GRAY",img2)
cv2.waitKey(0)
7.在一個(gè)窗口中顯示兩張圖片
import cv2
import numpy as np
img = cv2.imread("D:/test/resize.jpg")
img2 = cv2.imread("D:/test/resize.jpg")
#imgs = np.hstack([img,img2])#在水平方向上平鋪
imgs = np.vstack([img,img2])#在豎直方向上堆疊
cv2.imshow("mutil_pic", imgs)
cv2.waitKey(0)
8.繪圖功能
import cv2
import numpy as np
img = 255*np.ones((350,512,3),np.uint8)#unit8:0~255
#ones()為創(chuàng)建一個(gè)元素均為一的矩陣
font = cv2.FONT_HERSHEY_DUPLEX
#font = cv2.FONT_HERSHEY_COMPLEX# 設(shè)置字體
#文本 # 圖片對(duì)象、文本、 位置、 字體、字體大小、顏色、 字體粗細(xì)
cv2.putText(img, "happy day", (50,300), font, 0.8, (25, 25, 25), 2,)#顏色可以自己調(diào)整,范圍為0-255
#線 #起點(diǎn) 終點(diǎn) 顏色 粗細(xì)
cv2.line(img, (50,310), (185,310), (0, 0,0),4)
#矩形 #左上頂點(diǎn) 右下頂點(diǎn)
cv2.rectangle(img, (80,8), (200,100), (0, 255,0),2)
#圓形 #圓心 半徑 顏色 控制是否填充 -1表示填充
cv2.circle(img,(60,60),30,(0,0,213),1)
#橢圓 #中心點(diǎn) 長(zhǎng)軸 短軸 偏轉(zhuǎn)角度,起始角度,終止角度
cv2.ellipse(img,(100,300),(100,50),180,0,360,(20,213,79),1)
cv2.imshow("Draw", img)
cv2.waitKey(0)
1.np.vstack([img1,img2]) 當(dāng)img1和img2圖片矩陣維度相同時(shí)才能堆疊
2.除了imread,imwrite 函數(shù)沒有返回值以外,flip,resize,cvtColor,vstack,hstack都有返回一個(gè)圖片回來。
這是一個(gè)文件讀函數(shù)
我們很容易看出輸入?yún)?shù)中
filp 是文件
buf 是文件要讀到什么地方去,用戶buf
count是要讀多少東西
那么ppos是什么東東,是當(dāng)前文件的偏移量嘛??
但是當(dāng)前文件的偏移量在filp中有定義呀。struct file {
struct list_head f_list;
struct dentry *f_dentry;
struct vfsmount *f_vfsmnt;
struct file_operations *f_op;
atomic_t f_count;
unsigned int f_flags;
mode_t f_mode;
loff_t f_pos;//這個(gè)就是當(dāng)前文件的偏移量,我認(rèn)為struct file 中的f_pos是最后一次文件操作以后的當(dāng)前讀寫位置。而ppos是這次對(duì)文件進(jìn)行操作的起始位置,這兩個(gè)值不一定相等。
#?標(biāo)有"#"的行是修改過的,對(duì)比一下看看。
class?LightSwitch:
def?__init__(self,condition):
self.is_on?=?condition
if?not?isinstance(condition,bool):
InvaildSwitchExpection?=?TypeError("it?is?not?a?right?state".format(condition))
raise?InvaildSwitchExpection
def?turn_on(self):
self.is_on?=?True
def?turn_off(self):
self.is_on?=?False
def?filp(self):
if?self.is_on?==?False:
self.is_on?=?True
else:
self.is_on?=?False
def?__str__(self):
if?self.is_on?==?True:
return?"I?am?on"
else:
return?"I?am?off"
class?SwitchBoard(LightSwitch):
def?__init__(self,?number):
self._lights?=?[]
for?i?in?range(0,?number):
i?=?LightSwitch(False)
self._lights.append(i)
def?which_switch(self):
result?=?[]
for?i?in?range(0,?len(self._lights)):
if?self._lights[i].is_on?==?True:
result.append(str(i))?#
return?result
def?__str__(self):
result?=?self.which_switch()?#
result_str?=?','.join(result)
return?'The?following?switches?are?on:?'?+?result_str
def?filp(self,?n):
if?self._lights[n]?==?False:
self._lights[n].is_on?=?True
else:
self._lights[n].is_on?=?False
def?filp_every(self,?n):
k?=?0
while?n?*?k?=?len(self._lights)?-?1:
if?self._lights[n?*?k].is_on?==?False:
self._lights[n?*?k].is_on?=?True
else:
self._lights[n?*?k].is_on?=?False
k?=?k?+?1
def?reset(self):
for?light?in?self._lights:
light.is_on?=?False?#
light_board?=?SwitchBoard(10)
print(light_board)
light_board.filp_every(2)
print(light_board)
light_board.filp(2)
print(light_board)
light_board.reset()
print(light_board)
light_board.filp_every(1)
print(light_board)
有的代碼可以寫得更簡(jiǎn)潔,基類已經(jīng)提供的服務(wù)(接口),在派生類中直接使用就可以了。下面的僅供參考。
class?LightSwitch:
def?__init__(self,condition):
self.is_on?=?condition
if?not?isinstance(condition,bool):
InvaildSwitchExpection?=?TypeError("it?is?not?a?right?state".format(condition))
raise?InvaildSwitchExpection
def?turn_on(self):
self.is_on?=?True
def?turn_off(self):
self.is_on?=?False
def?filp(self):
self.is_on?=?not?self.is_on?##
def?__str__(self):
if?self.is_on?==?True:
return?"I?am?on"
else:
return?"I?am?off"
class?SwitchBoard(LightSwitch):
def?__init__(self,?number):
self._lights?=?[]
for?i?in?range(number):
i?=?LightSwitch(False)
self._lights.append(i)
def?which_switch(self):
result?=?[]
for?i?in?range(len(self._lights)):?##
if?self._lights[i].is_on?==?True:
result.append(str(i))?#
return?result
def?__str__(self):
result?=?self.which_switch()?#
result_str?=?','.join(result)
return?'The?following?switches?are?on:?'?+?result_str
def?filp(self,?n):
self._lights[n].filp()?##
def?filp_every(self,?n):
k?=?0
while?n?*?k?=?len(self._lights)?-?1:
self.filp(n?*?k)?##
k?=?k?+?1
def?reset(self):
for?light?in?self._lights:
light.turn_off()?##
light_board?=?SwitchBoard(10)
print(light_board)
light_board.filp_every(2)
print(light_board)
light_board.filp(2)
print(light_board)
light_board.reset()
print(light_board)
light_board.filp_every(1)
print(light_board)