python简单图片处理
環(huán)境:python3.6
PyQt 5.11.3
cython 0.28.7
guiqwt 3.0.3
opencv-python 3.4.3
項目要求是軟件通過CCD傳感器采集激光并分析數(shù)據(jù)。
現(xiàn)在開發(fā)階段沒有硬件設備,用手機連接到電腦上代替攝像頭。手機上用的DroidCamX,電腦上用的Droidcam Client。
首先采集攝像頭的圖像并轉換成灰度圖,然后轉換成彩虹圖。
PyQt分線程采集圖像數(shù)據(jù)并轉換成灰度圖,然后將灰度圖數(shù)據(jù)發(fā)送到主線程。
#device.py
# -*- coding:utf-8 -*-import cv2,time from PyQt5.QtCore import pyqtSignal,QThread import numpy as npclass ccd_dev(QThread):datasignal = pyqtSignal(int,list)def __init__(self):super(ccd_dev, self).__init__(parent=None)self.stop = 0def run(self):cap = cv2.VideoCapture(0)while 1:#print('start')time.sleep(0.001)if cap.isOpened():ret,frame = cap.read()if ret:clr = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)self.datasignal.emit(1,list(clr))if self.stop:cap.release()breakdef set_stop(self):self.stop = 1需要將灰度圖轉換成彩虹圖,用matplotlib的cmap刷新太慢,所以要使用自制彩虹圖算法。
參照了這個https://blog.csdn.net/michaelhan3/article/details/70833648
但是圖像數(shù)據(jù)大小是1280*640,python性能有限速度很慢,大概在0.7秒左右才能計算一次,所以采用Cython。
參照網(wǎng)上的碎片信息,試著做了一下。calxd是將灰度圖轉換成彩虹圖的算法,calxm是找出各行最大值組成一維數(shù)組,各列最大值組成一維數(shù)組。
#calc.pyx
import numpy as np cimport numpy as np cimport cython DTYPE = np.uint8 DTYPE1 = np.intctypedef np.uint8_t DTYPE_t ctypedef np.int_t DTYPE1_t@cython.boundscheck(False) @cython.wraparound(False) def calxd(np.ndarray[DTYPE_t,ndim=2] data):cdef int height, width ,i ,jcdef unsigned char num, r, g, b#0-255height = data.shape[0]width = data.shape[1]cdef np.ndarray[DTYPE_t, ndim=3] rgb = np.zeros([height,width,3],dtype=DTYPE)#3維,全為零的數(shù)組for i in range(height):for j in range(width):num = data[i,j]if num <=25:#在彩虹圖算法的基礎上增加了灰色b = num * 1g = num * 1r = num * 1elif num <= 51:num -= 25b = 255g = num * 5r = 0elif num <= 102:num -= 51b = 255 - num * 5g = 255r = 0elif num <= 153:num -= 102b = 0g = 255r = num * 5elif num <= 204:num -= 153b = 0g = 255 - <unsigned char>(128 * num / 51 + 0.5)#類型轉換r = 255else:num -= 204b = 0g = 127 - <unsigned char>(127 * num / 51 + 0.5)r = 255#rgb[i,j] = [r,g,b]#這種太慢rgb[i,j,0] = rrgb[i,j,1] = grgb[i,j,2] = breturn rgb@cython.boundscheck(False) @cython.wraparound(False) def calxm(np.ndarray[DTYPE_t,ndim=2] data):cdef int i, j, height, width, max, numheight = data.shape[0]width = data.shape[1]cdef np.ndarray[DTYPE_t, ndim=1] ver = np.zeros([height],dtype=DTYPE)cdef np.ndarray[DTYPE_t, ndim=1] hor = np.zeros([width],dtype=DTYPE)cdef np.ndarray[DTYPE1_t, ndim=1] x = np.zeros([width],dtype=DTYPE1)cdef np.ndarray[DTYPE1_t, ndim=1] y = np.zeros([height],dtype=DTYPE1)cdef np.ndarray[DTYPE_t, ndim=2] d1 = np.transpose(data)#轉置數(shù)組#ver = [max(dat) for dat in data]#這種超慢for i in range(height):max = data[i,0]y[i] = height - ifor j in range(width):num = data[i,j]if num > max:max = numver[i] = maxfor i in range(width):x[i] = imax = d1[i,0]for j in range(height):num = d1[i,j]if num > max:max = numhor[i] = maxreturn ver,hor,x,y然后創(chuàng)建一個setup.py文件,準備編譯,因為calc.pyx文檔里包含了
cimport numpy as np所以setup文件要加入
include_dirs=[np.get_include()]#setup.py
from distutils.core import setup from Cython.Build import cythonize import numpy as np setup(name='calculation', ext_modules=cythonize('calc.pyx'),include_dirs=[np.get_include()])在cmd命令行cd到當前路徑,并輸入python setup.py build_ext ?--inplace
編譯完成大概是這個樣子
編譯完成文件夾會出現(xiàn)兩個后綴名為*.c和*.pyd的文件。
然后測試一下編譯的代碼運行的速度
#test13.py
import cv2 import calc import timeimg2 = cv2.imread('123.png')img = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)height,width = img.shapestart = time.time() calc.calxd(img) end = time.time() print(end-start) m,n,x,y = calc.calxm(img) end2 = time.time()print(end2-end)測試結果:非常快,比之前的0.7秒快很多了
主程序圖表用的是guiqwt,是因為刷新比較快,matplotlib刷新太慢了。
#chart.py
import cv2,time,sys import numpy as np from PyQt5.QtWidgets import QWidget, QLabel, QVBoxLayout, QApplication, QHBoxLayout from PyQt5.QtGui import QImage, QPixmap, QPainter from PyQt5.QtCore import Qtimport calc from guiqwt.plot import CurveWidget from guiqwt.builder import make from device import ccd_devclass chart(QWidget):def __init__(self):super(chart, self).__init__(parent=None)#self.resize(800,600)self.win1 = CurveWidget()self.win1.setFixedWidth(170)self.curve = make.curve([],[])#縱向的圖表self.plot = self.win1.get_plot()self.plot.add_item(self.curve)self.plot.set_axis_limits(2,0,255)#X軸范圍self.plot.set_axis_title(0,'Y')#Y軸標簽self.plot.set_axis_title(2,'Z')#X軸標簽self.plot.grid.setMajorPen(Qt.DotLine)#大網(wǎng)格實線QtGui.QPen類self.plot.grid.setMajorPen(QColor('#e9e9e9'))#大網(wǎng)格顏色self.plot.grid.setMinorPen(Qt.NoPen)#小網(wǎng)格不可見self.win2 = CurveWidget()self.win2.setFixedHeight(150)self.curve2 = make.curve([],[])self.plot2 = self.win2.get_plot()self.plot2.add_item(self.curve2)self.plot2.set_axis_limits(0,0,255)self.plot2.set_axis_title(0,'Z')self.plot2.set_axis_title(2,'X')self.plot2.grid.setMajorPen(Qt.DotLine)#大網(wǎng)格實線QtGui.QPen類self.plot2.grid.setMajorPen(QColor('#e9e9e9'))#大網(wǎng)格顏色self.plot2.grid.setMinorPen(Qt.NoPen)#小網(wǎng)格不可見self.lab = QLabel()#顯示圖片的載體,不知道為什么vbox1 = QVBoxLayout()#為了圖表曲線高度和圖片高度一致vbox1.addWidget(self.lab)vbox1.addStretch(0)hbox = QHBoxLayout()hbox.addWidget(self.win1)hbox.addLayout(vbox1)hbox2 = QHBoxLayout()#為了圖表曲線長度和圖片長度一致hbox2.addStretch(0)hbox2.addWidget(self.win2)vbox = QVBoxLayout(self)vbox.addLayout(hbox)vbox.addLayout(hbox2)self.th = ccd_dev()#采集圖像的分線程self.th.datasignal.connect(self.slot_data)self.th.start()def slot_data(self,i,img):#t1 = time.time()clr = np.array(img)#Type:list -> np.array,灰度圖數(shù)據(jù)height, width = clr.shapeself.lab.setFixedSize(width,height)self.win1.setFixedHeight(height+35)self.win2.setFixedWidth(width+47)rgb = calc.calxd(clr)#自制彩虹圖的算法ver, hor, x, y = calc.calxm(clr)#ver是每一行的最大值集合,hor是每一列的最大值集合self.curve.set_data(ver,y)#更新圖表self.curve2.set_data(x,hor)image = QImage(rgb,width,height,QImage.Format_RGB888)#QImage.Format_Indexed8顯示為灰度圖self.lab.setPixmap(QPixmap.fromImage(image))#顯示圖片#t2 = time.time()#print(t2 - t1)#測量部分代碼運行時間if __name__ == '__main__':app = QApplication(sys.argv)ar = chart()ar.show()sys.exit(app.exec_())界面是這樣
總結
以上是生活随笔為你收集整理的python简单图片处理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关闭笔记本电脑计算机键盘,笔记本小键盘怎
- 下一篇: 3dmax2020软件安装教程