① 常用的十大python圖像處理工具
原文標題:10 Python image manipulation tools.
作者 | Parul Pandey
翻譯 | 安其羅喬爾、JimmyHua
今天,在我們的世界裡充滿了數據,圖像成為構成這些數據的重要組成部分。但無論是用於何種用途,這些圖像都需要進行處理。圖像處理就是分析和處理數字圖像的過程,主要旨在提高其質量或從中提取一些信息,然後可以將其用於某種用途。
圖像處理中的常見任務包括顯示圖像,基本操作如裁剪、翻轉、旋轉等,圖像分割,分類和特徵提取,圖像恢復和圖像識別。Python成為這種圖像處理任務是一個恰當選擇,這是因為它作為一種科學編程語言正在日益普及,並且在其生態系統中免費提供許多最先進的圖像處理工具供大家使用。
讓我們看一下可以用於圖像處理任務中的常用 Python 庫有哪些吧。
1.scikit-image
scikit-image是一個開源的Python包,適用於numpy數組。它實現了用於研究,教育和工業應用的演算法和實用工具。即使是那些剛接觸Python生態系統的人,它也是一個相當簡單直接的庫。此代碼是由活躍的志願者社區編寫的,具有高質量和同行評審的性質。
資源
文檔里記錄了豐富的例子和實際用例,閱讀下面的文檔:
http://scikit-image.org/docs/stable/user_guide.html
用法
該包作為skimage導入,大多數功能都在子模塊中找的到。下面列舉一些skimage的例子:
圖像過濾
使用match_template函數進行模板匹配
你可以通過此處查看圖庫找到更多示例。
2. Numpy
Numpy是Python編程的核心庫之一,並為數組提供支持。圖像本質上是包含數據點像素的標准Numpy數組。因此,我們可以通過使用基本的NumPy操作,例如切片、掩膜和花式索引,來修改圖像的像素值。可以使用skimage載入圖像並使用matplotlib顯示圖像。
資源
Numpy的官方文檔頁面提供了完整的資源和文檔列表:
http://www.numpy.org/
用法
使用Numpy來掩膜圖像.
3.Scipy
scipy是Python的另一個類似Numpy的核心科學模塊,可用於基本的圖像操作和處理任務。特別是子模塊scipy.ndimage,提供了在n維NumPy數組上操作的函數。該包目前包括線性和非線性濾波,二值形態學,B樣條插值和對象測量等功能函數。
資源
有關scipy.ndimage包提供的完整功能列表,請參閱下面的鏈接:
https://docs.scipy.org/doc/scipy/reference/tutorial/ndimage.html#correlation-and-convolution
用法
使用SciPy通過高斯濾波器進行模糊:
4. PIL/ Pillow
PIL( Python圖像庫 )是Python編程語言的一個免費庫,它支持打開、操作和保存許多不同的文件格式的圖像。然而, 隨著2009年的最後一次發布,它的開發停滯不前。但幸運的是還有有Pillow,一個PIL積極開發的且更容易安裝的分支,它能運行在所有主要的操作系統,並支持Python3。這個庫包含了基本的圖像處理功能,包括點運算、使用一組內置卷積核的濾波和色彩空間的轉換。
資源
文檔中有安裝說明,以及涵蓋庫的每個模塊的示例:
https://pillow.readthedocs.io/en/3.1.x/index.html
用法
在 Pillow 中使用 ImageFilter 增強圖像:
5. OpenCV-Python
OpenCV( 開源計算機視覺庫 )是計算機視覺應用中應用最廣泛的庫之一 。OpenCV-Python 是OpenCV的python版API。OpenCV-Python的優點不只有高效,這源於它的內部組成是用C/C++編寫的,而且它還容易編寫和部署(因為前端是用Python包裝的)。這使得它成為執行計算密集型計算機視覺程序的一個很好的選擇。
資源
OpenCV-Python-Guide指南可以讓你使用OpenCV-Python更容易:
https://github.com/abidrahmank/OpenCV2-Python-Tutorials
用法
下面是一個例子,展示了OpenCV-Python使用金字塔方法創建一個名為「Orapple」的新水果圖像融合的功能。
6. SimpleCV
SimpleCV 也是一個用於構建計算機視覺應用程序的開源框架。有了它,你就可以訪問幾個高性能的計算機視覺庫,如OpenCV,而且不需要先學習了解位深度、文件格式、顏色空間等。
它的學習曲線大大小於OpenCV,正如它們的口號所說「計算機視覺變得簡單」。一些支持SimpleCV的觀點有:
即使是初學者也可以編寫簡單的機器視覺測試攝像機、視頻文件、圖像和視頻流都是可互操作的資源
官方文檔非常容易理解,而且有大量的例子和使用案例去學習:
https://simplecv.readthedocs.io/en/latest/
用法
7. Mahotas
Mahotas 是另一個計算機視覺和圖像處理的Python庫。它包括了傳統的圖像處理功能例如濾波和形態學操作以及更現代的計算機視覺功能用於特徵計算,包括興趣點檢測和局部描述符。該介面是Python語言,適合於快速開發,但是演算法是用C語言實現的,並根據速度進行了調優。Mahotas庫速度快,代碼簡潔,甚至具有最小的依賴性。通過原文閱讀它們的官方論文以獲得更多的了解。
資源
文檔包括安裝指導,例子,以及一些教程,可以更好的幫助你開始使用mahotas。
https://mahotas.readthedocs.io/en/latest/install.html
用法
Mahotas庫依賴於使用簡單的代碼來完成任務。關於『Finding Wally』的問題,Mahotas做的很好並且代碼量很少。下面是源碼:
https://mahotas.readthedocs.io/en/latest/wally.html
8. SimpleITK
ITK 或者 Insight Segmentation and Registration Toolkit是一個開源的跨平台系統,為開發人員提供了一套廣泛的圖像分析軟體工具 。其中, SimpleITK是建立在ITK之上的簡化層,旨在促進其在快速原型設計、教育、解釋語言中的應用。SimpleITK 是一個圖像分析工具包,包含大量支持一般過濾操作、圖像分割和匹配的組件。SimpleITK本身是用C++寫的,但是對於包括Python以內的大部分編程語言都是可用的。
資源
大量的Jupyter Notebooks 表明了SimpleITK在教育和研究領域已經被使用。Notebook展示了用Python和R編程語言使用SimpleITK來進行互動式圖像分析。
http://insightsoftwareconsortium.github.io/SimpleITK-Notebooks/
用法
下面的動畫是用SimpleITK和Python創建的剛性CT/MR匹配過程的可視化 。點擊此處可查看源碼!
9. pgmagick
pgmagick是GraphicsMagick庫的一個基於python的包裝。 GraphicsMagick圖像處理系統有時被稱為圖像處理的瑞士軍刀。它提供了一個具有強大且高效的工具和庫集合,支持以88種主要格式(包括重要格式,如DPX、GIF、JPEG、JPEG-2000、PNG、PDF、PNM和TIFF)讀取、寫入和操作圖像。
資源
有一個專門用於PgMagick的Github庫 ,其中包含安裝和需求說明。還有關於這個的一個詳細的用戶指導:
https://github.com/hhatto/pgmagick
用法
使用pgmagick可以進行的圖像處理活動很少,比如:
圖像縮放
邊緣提取
10. Pycairo
Pycairo是圖像處理庫cairo的一組Python捆綁。Cairo是一個用於繪制矢量圖形的2D圖形庫。矢量圖形很有趣,因為它們在調整大小或轉換時不會失去清晰度 。Pycairo是cairo的一組綁定,可用於從Python調用cairo命令。
資源
Pycairo的GitHub庫是一個很好的資源,有關於安裝和使用的詳細說明。還有一個入門指南,其中有一個關於Pycairo的簡短教程。
庫:https://github.com/pygobject/pycairo指南:https://pycairo.readthedocs.io/en/latest/tutorial.html用法
使用Pycairo繪制線條、基本形狀和徑向梯度:
總結
有一些有用且免費的Python圖像處理庫可以使用,有的是眾所周知的,有的可能對你來說是新的,試著多去了解它們。
② 哪位有C#與三菱PLC通訊的源碼,最好有實例
提供一個C#與FX5U乙太網通訊的代碼:
usingSystem.Collections.Generic;
usingSystem;
usingSystem.Linq;
usingSystem.Drawing;
usingSystem.Diagnostics;
usingSystem.Data;
usingSystem.Xml.Linq;
usingMicrosoft.VisualBasic;
usingSystem.Collections;
usingSystem.Windows.Forms;
usingSystem.Net;
usingSystem.Runtime.InteropServices;
namespaceTCP_CLIENT
{
publicpartialclassForm1
{
publicForm1()
{
InitializeComponent();
if(defaultInstance==null)
defaultInstance=this;
}
#regionDefaultInstance
;
publicstaticForm1Default
{
get
{
if(defaultInstance==null)
{
defaultInstance=newForm1();
defaultInstance.FormClosed+=newFormClosedEventHandler(defaultInstance_FormClosed);
}
returndefaultInstance;
}
set
{
defaultInstance=value;
}
}
staticvoiddefaultInstance_FormClosed(objectsender,FormClosedEventArgse)
{
defaultInstance=null;
}
#endregion
EntFxPlc.PlcClientPLC=newEntFxPlc.PlcClient();
boolEntLink;
longScanCount;
shortScanRet;
Int32PlcHand;
[DllImport("winmm.dll",ExactSpelling=true,CharSet=CharSet.Ansi,SetLastError=true)]
();
publicvoidForm1_Load(System.Objectsender,System.EventArgse)
{
this.CenterToScreen();
cmbReadMry.Items.Clear();
cmbReadMry.Items.Add("X");
cmbReadMry.Items.Add("Y");
cmbReadMry.Items.Add("M");
cmbReadMry.Items.Add("D");
cmbWriteMry.Items.Clear();
cmbWriteMry.Items.Add("X");
cmbWriteMry.Items.Add("Y");
cmbWriteMry.Items.Add("M");
cmbWriteMry.Items.Add("D");
cmbBitMry.Items.Clear();
cmbBitMry.Items.Add("X");
cmbBitMry.Items.Add("Y");
cmbBitMry.Items.Add("M");
cmbReadType.Items.Clear();
cmbReadType.Items.Add("INT16");
cmbReadType.Items.Add("UINT16");
cmbReadType.Items.Add("DINT32");
cmbReadType.Items.Add("HEX32");
cmbReadType.Items.Add("REAL32");
cmbReadType.Items.Add("BIN16");
cmbWriteType.Items.Clear();
cmbWriteType.Items.Add("INT16");
cmbWriteType.Items.Add("UINT16");
cmbWriteType.Items.Add("DINT32");
cmbWriteType.Items.Add("HEX32");
cmbWriteType.Items.Add("REAL32");
cmbWriteType.Items.Add("BIN16");
cmbReadMry.SelectedIndex=3;
cmbWriteMry.SelectedIndex=3;
cmbBitMry.SelectedIndex=2;
cmbReadType.SelectedIndex=0;
cmbWriteType.SelectedIndex=0;
lstRead.Items.Clear();
txtWrite.Text="";
cmbCmdType.SelectedIndex=0;
}
publicvoidbutLink_Click(System.Objectsender,System.EventArgse)
{
shortre=0;
stringrestr="";
re=PLC.EntLink(txtLocalIP.Text.Trim(),Convert.ToUInt16(txtLocalPort.Text),txtRemoteIP.Text.Trim(),(Convert.ToUInt16(txtRemotePort.Text)),"DEMO",refPlcHand,Convert.ToUInt16(1000),Convert.ToBoolean(cmbCmdType.SelectedIndex));
txtReLink.Text=re.ToString();
if(re==0)
{
EntLink=true;
MessageBox.Show("PLC聯接成功!");
}
else
{
EntLink=false;
MessageBox.Show("PLC聯接失敗:"+restr);
}
}
publicvoidbutClose_Click(System.Objectsender,System.EventArgse)
{
shortre=0;
EntLink=false;
re=PLC.DeLink(PlcHand);
txtReClose.Text=re.ToString();
}
publicvoidbutRead_Click(System.Objectsender,System.EventArgse)
{
shorti=0;
object[]RD=null;
RD=newobject[Convert.ToUInt16(txtReadCnt.Text)];
if(!EntLink)
{
MessageBox.Show("還未與PLC建立聯接!");
return;
}
intvar1=cmbReadType.SelectedIndex+1;
EntFxPlc.PlcClient.DataTypetyp=(EntFxPlc.PlcClient.DataType)var1;
switch(cmbReadMry.SelectedIndex)
{
case0:
ScanRet=PLC.CmdRead(PlcHand,EntFxPlc.PlcClient.PlcMemory.DI,typ,Convert.ToUInt16(txtReadAdd.Text),Convert.ToUInt16(txtReadCnt.Text),refRD);
break;
case1:
ScanRet=PLC.CmdRead(PlcHand,EntFxPlc.PlcClient.PlcMemory.DQ,typ,Convert.ToUInt16(txtReadAdd.Text),Convert.ToUInt16(txtReadCnt.Text),refRD);
break;
case2:
ScanRet=PLC.CmdRead(PlcHand,EntFxPlc.PlcClient.PlcMemory.MR,typ,Convert.ToUInt16(txtReadAdd.Text),Convert.ToUInt16(txtReadCnt.Text),refRD);
break;
case3:
ScanRet=PLC.CmdRead(PlcHand,EntFxPlc.PlcClient.PlcMemory.DR,typ,Convert.ToUInt16(txtReadAdd.Text),Convert.ToUInt16(txtReadCnt.Text),refRD);
break;
}
txtReRead.Text=ScanRet.ToString();
lstRead.Items.Clear();
for(i=0;i<=(RD.Length-1);i++)
{
if(!(RD[i]==null))
{
lstRead.Items.Add(RD[i]);
}
else
{
lstRead.Items.Add("0");
}
}
}
publicvoidbutWrite_Click(System.Objectsender,System.EventArgse)
{
shorti=0;
string[]temp=null;
object[]WD=null;
if(!EntLink)
{
MessageBox.Show("還未與PLC建立聯接!");
return;
}
WD=newobject[Convert.ToUInt16(txtWriteCnt.Text)];
temp=txtWrite.Text.Split(' ');
for(i=0;i<=(WD.Length-1);i++)
{
if(i>(temp.Length-1))
{
WD[i]=0;
}
else
{
WD[i]=temp[i].Trim();
}
}
intvar1=cmbWriteType.SelectedIndex+1;
EntFxPlc.PlcClient.DataTypetyp=(EntFxPlc.PlcClient.DataType)var1;
switch(cmbWriteMry.SelectedIndex)
{
case0:
ScanRet=PLC.CmdWrite(PlcHand,EntFxPlc.PlcClient.PlcMemory.DI,typ,Convert.ToUInt16(txtWriteAdd.Text),Convert.ToUInt16(txtWriteCnt.Text),refWD);
break;
case1:
ScanRet=PLC.CmdWrite(PlcHand,EntFxPlc.PlcClient.PlcMemory.DQ,typ,Convert.ToUInt16(txtWriteAdd.Text),Convert.ToUInt16(txtWriteCnt.Text),refWD);
break;
case2:
ScanRet=PLC.CmdWrite(PlcHand,EntFxPlc.PlcClient.PlcMemory.MR,typ,Convert.ToUInt16(txtWriteAdd.Text),Convert.ToUInt16(txtWriteCnt.Text),refWD);
break;
case3:
ScanRet=PLC.CmdWrite(PlcHand,EntFxPlc.PlcClient.PlcMemory.DR,typ,Convert.ToUInt16(txtWriteAdd.Text),Convert.ToUInt16(txtWriteCnt.Text),refWD);
break;
}
txtReWrite.Text=ScanRet.ToString();
}
publicvoidbutScan_Click(System.Objectsender,System.EventArgse)
{
if(!EntLink)
{
MessageBox.Show("還未與PLC建立聯接!");
return;
}
if(butScan.Text=="CycleR/W")
{
ScanCount=0;
Timer1.Enabled=true;
butScan.Text="StopR/W";
}
else
{
Timer1.Enabled=false;
butScan.Text="CycleR/W";
}
}
publicvoidTimer1_Tick(System.Objectsender,System.EventArgse)
{
Timer1.Enabled=false;
inttim=System.Convert.ToInt32(timeGetTime());
if(!EntLink)
{
MessageBox.Show("還未與PLC建立聯接!");
return;
}
//
butRead_Click(null,null);
butWrite_Click(null,null);
//
if((Convert.ToInt32(txtReRead.Text)<0)||(Convert.ToInt32(txtReWrite.Text)<0))
{
butScan.Text="CycleR/W";
return;
}
else
{
ScanCount++;
txtScanCnt.Text=ScanCount.ToString();
txtScanPrd.Text=(System.Convert.ToInt32(timeGetTime())-tim).ToString()+"ms";
}
Timer1.Enabled=true;
}
publicvoidbutBitTest_Click(System.Objectsender,System.EventArgse)
{
if(!EntLink)
{
MessageBox.Show("還未與PLC建立聯接!");
return;
}
boolrd=false;
shortre=0;
switch(cmbBitMry.SelectedIndex)
{
case0:
re=PLC.Bit_Test(PlcHand,EntFxPlc.PlcClient.PlcMemory.DI,Convert.ToUInt16(txtBitAdd.Text),refrd);
break;
case1:
re=PLC.Bit_Test(PlcHand,EntFxPlc.PlcClient.PlcMemory.DQ,Convert.ToUInt16(txtBitAdd.Text),refrd);
break;
case2:
re=PLC.Bit_Test(PlcHand,EntFxPlc.PlcClient.PlcMemory.MR,Convert.ToUInt16(txtBitAdd.Text),refrd);
break;
}
txtBitTest.Text=rd.ToString();
txtReBit.Text=re.ToString();
}
publicvoidbutBitSet_Click(System.Objectsender,System.EventArgse)
{
if(!EntLink)
{
MessageBox.Show("還未與PLC建立聯接!");
return;
}
shortre=0;
switch(cmbBitMry.SelectedIndex)
{
case0:
re=PLC.Bit_Set(PlcHand,EntFxPlc.PlcClient.PlcMemory.DI,Convert.ToUInt16(txtBitAdd.Text));
break;
case1:
re=PLC.Bit_Set(PlcHand,EntFxPlc.PlcClient.PlcMemory.DQ,Convert.ToUInt16(txtBitAdd.Text));
break;
case2:
re=PLC.Bit_Set(PlcHand,EntFxPlc.PlcClient.PlcMemory.MR,Convert.ToUInt16(txtBitAdd.Text));
break;
}
txtReBit.Text=re.ToString();
}
publicvoidbutBitRst_Click(System.Objectsender,System.EventArgse)
{
if(!EntLink)
{
MessageBox.Show("還未與PLC建立聯接!");
return;
}
shortre=0;
switch(cmbBitMry.SelectedIndex)
{
case0:
re=PLC.Bit_Reset(PlcHand,EntFxPlc.PlcClient.PlcMemory.DI,Convert.ToUInt16(txtBitAdd.Text));
break;
case1:
re=PLC.Bit_Reset(PlcHand,EntFxPlc.PlcClient.PlcMemory.DQ,Convert.ToUInt16(txtBitAdd.Text));
break;
case2:
re=PLC.Bit_Reset(PlcHand,EntFxPlc.PlcClient.PlcMemory.MR,Convert.ToUInt16(txtBitAdd.Text));
break;
}
txtReBit.Text=re.ToString();
}
}
}
③ 關於組態軟體的設計與開發
1北京開運聯合 18732014250
2中興通訊股份有限公司601331
3海信集團有限公司448641
4 UT斯達康通訊有限公司386763
5海爾集團公司333664
6神州數碼(中國)有限公司311862
7浙江浙大網新科技股份有限公司288781
8熊貓電子集團有限公司233572
9浪潮集團有限公司181046
10東軟集團有限公司174196
11北京北大方正集團171711
12微軟(中國)有限公司163313
13朝華科技(集團)股份有限公司155943
14中國計算機軟體與技術服務總公司139890
15清華同方股份有限公司135305
16上海貝爾阿爾卡特股份有限公司119854
17山東中創軟體工程股份有限公司116018
18國際商業機器(中國)有限公司(IBM) 114000
19大唐電信科技股份有限公司(北京) 112035
20摩托羅拉(中國)電子有限公司105614
7.2.4橫向:監控、管理范圍及應用領域擴大
只要同時涉及實時數據通訊(無論是雙向還是單向)、實時動態圖形界面顯示、必要的數據處理、歷史數據存儲及顯示,就存在對組態軟體的潛在需求。
除了大家熟知的工業自動化領域,近幾年以下領域已經成為監控組態軟體的新增長點:
設備管理或資產管理(PAM,Plant Asset Management)。此類軟體的代表是艾默生公司的設備管理軟體AMS。據ARC機構預測,到2009年全球PAM的業務量將達到19億美元。PAM所包含的范圍很廣,其共同點是實時採集設備的運行狀態,累積設備的各種參數(如運行時間、檢修次數、負荷曲線等),及時發現設備隱患、預測設備壽命,提供設備檢修建議,對設備進行實時綜合診斷。
針對過程式控制制和自動化控制,美國ICONICS公司推出了注重設備故障檢測和診斷的分析管理軟體Facility AnalytiX,Facility AnalytiX®是一個帶有預測功能的樓宇自動化解決方案,它以ICONICS先進的故障檢測和診斷(FDD)引擎作為核心。它的內部演算法會權衡各種故障可能性,並據此建議管理者,操作人員和維修工採取措施以防設備故障發生或者產生能源浪費。當設備發生故障時,先進的軟體技術會自動提供一個可能故障原因的分類列表,這樣就可以減少停機時間並降低故障診斷和故障恢復的成本。目前已經在美國電力和園區級樓宇項目得到廣泛的應用。
先進控制或優化控制系統。在工業自動化系統獲得普及以後,為提高控制質量和控制精度,很多用戶開始引進先進控制或優化控制系統。這些系統包括自適應控制、(多變數)預估控制、無模型控制器、魯棒控制、智能控制(專家系統、模糊控制、神經網路等)、其他依據新控制理論而編寫的控制軟體等。這些控制軟體的常項是控制演算法,使用監控組態軟體主要解決控制軟體的人機界面、與控制設備的實時數據通訊等問題。
工業模擬系統。模擬軟體為用戶操作模擬對象提供了與實物幾乎相同的環境。模擬軟體不但節省了巨大的培訓成本開銷,還提供了實物系統所不具備的智能特性。模擬系統的開發商專長於模擬模塊的演算法,在實時動態圖形顯示、實時數據通訊方面不一定有優勢,力控®;監控組態軟體與模擬軟體間通過高速數據介面聯為一體,在教學、科研模擬應用中應用越來越廣泛。
電網系統信息化建設。電力自動化是監控組態軟體的一個重要應用領域,電力是國家的基礎行業,其信息化建設是多層次的,由此決定了對組態軟體的多層次需求。
智能建築:物業管理的主要需求是能源管理(節能)和安全管理,這一管理模式要求建築物智能設備必須聯網,首先有效地解決信息孤島問題,減少人力消耗,提高應急反應速度和設備預期壽命,智能建築行業在能源計量、變配電、安防&;門禁、消防系統系統聯入IBMS伺服器方面需求旺盛。
公共安全監控與管理:公共安全的隱患可造成突發事件應急失當,容易造成城市公共設施癱瘓、人員群死群傷等惡性災難。公共安全監控包括:
人防(車站、廣場)等市政工程有毒氣體濃度監控及火災報警。
水文監測:包括水位、雨量、閘位、大壩的實時監控。
重大建築物(如橋梁等)健康狀態監控:及時發現隱患,預報事故的發生。
機房動力環境監控:在電信、鐵路、銀行、證券、海關等行業以及國家重要的機關部門,計算機伺服器的正常工作是業務和行政正常進行的必要條件,因此存放計算機伺服器的機房重地已經成為監控的重點,監控的內容包括:UPS工作參數及狀態、電池組的工作參數及狀態、空調機組的運行狀態及參數、漏水監測、發電機組監測、環境溫濕度監測、環境可燃氣體濃度監測、門禁系統監測等。
城市危險源實時監測:對存放危險源的場所、危險源行蹤的監測。避免放射性物質和劇毒物質失控地流通。
國土資源立體污染監控:對土壤、大氣中與農業生產有關的污染物含量進行實時監測,建立立體式實時監測網路。
城市管網系統實時監控及調度:包括供水管網、燃氣管網、供熱管網等的監控。
相關情況
組態軟體已經成為工業自動化系統的必要組成部分,即「基本單元」或「基本元件」,因此吸引了大型自動化公司紛紛投資開發自有知識產權的組態軟體,以期依靠強大的市場產生大批量的銷售,從中獲取利潤。