• 3D列印服務
  • #maker+t=market
  • COSPLAY 3D 建模
  • 1
  • 2
  • 3

Python人工智慧圖控 - 研習交流廳 造訪社團 » 參考

原文網址 石小川
2020-03-27 15:51:22

上過我的課的同學應該知道, Qt5的Designer GUI拖拉元件還蠻方便開發APP的。如果熟悉Qt5且想更進一步在手機上執行你寫的應用程式,可參考下列方式建置Android下的Qt5開發環境。(至於IOS, 因為老師目前沒有iPhone就先不提了)。
繼上回介紹的手機程式開發工具Android Studio後,其實在手機上寫APP程式還有另一個選擇開發工具就是Qt5,我還挺喜歡用它的原因是無論Android版Qt5、Python版Pyqt5、Windows版Qt5,我只要維護一個程式碼就好,其他就只是環境移植而已,不是甚麼大工程,修改幅度不大。
QT5.10.0的Android 開發環境建置請參考下列連結 : https://blog.csdn.net/qq_28643619/article/details/86589252

Xi Kris
2020-03-27 15:59:33

請問像qt 這樣的拖拉GUI設計,在之後如果要進行layout 的重置會不會很容易出現問題。
(在python 程式碼以及XML檔之間的問題)

石小川
2020-03-27 16:06:16

不同機器的layout佈置一定要用相對位置, 移植才不會出大問題。

Qt Designer 儲存的是.ui檔,結構類似XML格式,因為我們期望是要給Python 引用,所以我們必須想辦法將.ui檔轉換成.py檔才行。 PyQt5提供一個命令列工具pyuic5可以很輕鬆地完成轉換工作,使用方式如下 : pyuic5 source.ui -o destination.py

Xi Kris
2020-03-29 15:59:48

想請問~ 如果是把layout的ui.檔跟python 程式碼分開這樣會不會比較方便之後的維護呢?

石小川
2020-03-29 19:55:47

Xi Kris 當然!

Xi Kris
2020-03-29 22:37:34

石小川 先生想請教您,
那如果使用pyuic5 將ui文件轉為py文件的話,如果更改layout 之後的話,是不是又要重整之前多添加的程式碼?
我還是pyqt初學者,有點不瞭解。
目前我是使用uic.loadUiType("xxx.ui")的方式把ui檔案引入IDE 編寫。
覺得這樣ui檔案如果更改的話,程式碼也不會受影響。
請問您都是用pyuic5的轉換來維護程式碼嗎?

石小川
2020-03-30 08:12:49

Xi Kris 可參考 第一單元 使用Python開發多軸運動控制機電系統 :
"Python + PyQt5 教學 - 圖控介面開發工具 QT Designer" 有詳細說明。


原文網址 石小川
2020-03-25 15:44:14

常聽到朋友談起學完程式設計(特別是學會Python爬蟲)後,不知道如何應用這個技能! 今天要介紹現代人必讀的兩本書。一本是大數據(Big data) 和另一本是如何衡量萬物(How to Measure Anything), 我會建議學完程式語言後,這兩本書可拿來當小說看看, 也許答案就在裡面。 (A)Big Data: A Revolution That Will Transform How We Live, Work, and Think (B)How to Measure Anything: Finding the Value of "Intangibles" in Business p.s. (A)Big Data是大數據原文書,(B)是如何衡量萬物也有中譯本,值得一看。 無論你身處在何種行業(包括學生), 讀完此書後各人感受不同, 雖不敢說你會脫胎換骨, 但至少可訓練你判斷人、事、時、地、物的邏輯分析能力.

巨量資料分析已經成為新的研究科學工具, 如果你懂的程式設計, 甚至可進一步實作出屬於你自己的大數據, 應用在分析問題及決策參考上. 我是覺得書中逆向思考的方式蠻有趣的, 值得推薦給對世界充滿好奇的朋友閱讀.

下列為其部份內容摘錄大數據:

巨量資料初試啼聲

說巧不巧,就在H1N1躍上新聞頭條的幾星期前,網路巨擘谷歌(Google)旗下的幾位工程師,在著名的《自然》科學期刊發表了一篇重要的論文,當時並未引起一般人的注意,只在衛生當局和電腦科學圈裡引起討論。該篇論文解釋了谷歌能如何「預測」美國在冬天即將爆發流感,甚至還能精準定位到是哪些州。

谷歌的祕訣,就是看看民眾在網路上搜尋些什麼。由於谷歌每天會接收到超過30億筆的搜尋,而且會把它們全部儲存起來,那就會有大量的資料得以運用。

谷歌先挑出美國人最常使用的前5,000萬個搜尋字眼,再與美國疾病管制局在2003年到2008年之間的流感傳播資料,加以比對。谷歌的想法,是想靠著民眾在網路上搜尋什麼關鍵詞,找出那些感染上流感的人。雖然也曾有人就網路搜尋字眼做過類似的努力,但是從來沒人能像谷歌一樣掌握巨量資料(Big Data,本書譯為大數據),並具備強大的處理能力和在統計上的專業技能。

雖然谷歌已經猜到,民眾的搜尋字眼可能與流感有關聯,像是「止咳退燒」,但有沒有因果關係並不是真正的重點,他們設計的系統也不是從這個角度出發。谷歌這套系統真正做的,是要針對搜尋字眼的搜尋頻率,找出和流感傳播的時間、地區,有沒有統計上的相關性(correlation)。他們總共用上了高達4.5億種不同的數學模型,測試各種搜尋字眼,再與疾管局在2007年與2008年的實際流感病例加以比較。他們可挖到寶了!這套軟體找出了一組共45個搜尋字眼,放進數學模型之後,預測結果會與官方公布的全美真實資料十分符合,有強烈的相關性。於是,他們就像疾管局一樣能夠掌握流感疫情,但可不是1、2星期之後的事,而是幾近即時同步的掌握!

因此,在2009年發生H1N1危機的時候,比起政府手中的資料(以及無可避免的通報延遲),谷歌系統能提供更有用、更即時的資訊。公衛當局有了這種寶貴的資訊,控制疫情如虎添翼。

最驚人的是,谷歌的這套方法並不需要去採集檢體、也不用登門造訪各家醫院診所,而只是好好利用了巨量資料,也就是用全新的方式來使用資訊,以取得實用且價值非凡的見解、商機或服務。有了谷歌這套系統,下次爆發流感的時候,全球就有了更佳的工具能夠加以預測,並防止疫情蔓延。

巨量資料功能強大,可以讓許多領域改頭換面,公共衛生領域不過是其中之一,而商業領域也正在經歷這個過程。


原文網址 石小川
2020-03-22 15:02:17

近期為了ROS(機器人作業系統)相關專案,於是想起了以前的小玩具 - ROVIO,塵封已久的路威機器人在倉庫找了許久,終於抓到這隻小烏龜了,檢查電池、發現零組件狀況不錯,可見保存很好,這個ROVIO機器人麻雀雖小卻五臟俱全,看看下面硬體規格就知道。分享給有興趣製作機器人的朋友做參考。 Rovio機器人主要特點: 內含麥克風及喇叭可以雙向語音交談 可以遙控攝影機頭上下移動 可以手機和電腦或者Pad遠程網路控制 可以自動充電 雷達偵測障礙 硬體規格: 是以三大電路板結合而成:
(1)主ARM 板
Main Processor —科宇KOI-MP802 蓋面
實際為華邦 W99702 內建mpeg壓縮 跑 WEB server ,rtsp , and 主機總控
制 "spook" media streaming server ( [Spook Live Video Streamer]
( http://www.litech.org/spook/ ) )
Clock frequency 200Mhz
Main Memory — 8MB RAM
USB ttl port 與電腦通訊 (以W99100DG實現,負責isp下載)
Audio chip WM8976
Web cam video chip OV7670
SPI FLASH(W25X16) 2MB
OS Open-source "eCos" (2)充電電路板:專用NiMH充電管理芯片LS2516,PWM恆流方式,
電流不詳,穩壓二極體用的是1N5822,估計>1A。 (3)驅動板 MCU:4路BJT H電橋,3個輪子用光柵反饋,攝像頭升降用
可變電阻反饋,紅外線訊號和主控板通過串口通訊。 自動導航電路以紅外線感應運算
充電基座會投射出紅外線導航點,車上再以紅外線感應器做幾何
定位.定位程式由專門晶片負責.再送出串口訊號回應給上位機定位訊息

海闊天
2020-03-22 15:42:03

這台夢幻超跑要賣多少錢啊?小川哥!

海闊天
2020-03-22 15:42:32

海闊天
2020-03-22 15:42:44

石小川
2020-03-22 17:31:46

2013年露天買的, 3000多台幣, 拿來解剖研究用! 哈哈!

詹俊英
2020-03-24 20:58:27


原文網址 石小川
2020-03-11 22:20:43

會用樹莓派直接控制四軸飛行器的飛控板理由是 : 你可以用一台筆電 + ROS(機器人作業系統)的資料鏈串連起來,就可指揮上百台無人飛行器做空中分列式,或幾百台水上無人艦艇跳芭蕾舞、、等等,當然前提是你要會寫些程式才行。 連接方式很簡單, 如圖綠色圈起來的就是Pixhawk通訊埠: 將飛控板Pixhawk上的Telem2接口四根線引出(其實就是UART): Telem2的5V接Pi的5V Telem2的TX接Pi的RX Telem2的RX接Pi的TX Telem2的GND接Pi的GND 這樣子筆電就可以和多個樹莓派通訊進而控制多個飛行器,當然中間還是有一言難盡的技術,再擇期說明。 軟體設定可參考下面教學,我就不重複了。 https://blog.csdn.net/liberatetheus/article/details/77968424 https://blog.csdn.net/Lin_QC/article/details/90373992?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task https://blog.csdn.net/weixin_42704669/article/details/83791117?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

林永仁
2020-03-14 21:46:38


原文網址 石小川
2020-03-07 18:57:10

當相同類型的程式時常使用或必須重複呼叫時,這時就是考慮將副程式加進程式庫的時候,我習慣將功能相同的函式放在一起製作專用的程式庫,例如處裡影像副程式放在TImage.dll、處裡語音副程式放在
TSpeech.dll、處裡神經網路程式放在TNeuron.dll、處裡光達程式放在TLidar.dll等等 , 一旦你的程式庫累計的夠多的話,將來設計APP應用程式就會如同貼圖一樣方便,只要呼叫程式庫就好,主程式變少了。 接下來Demo一個動態程式庫TSystem.dll,裡面函式是負責儲存使用者最後操作各個視窗元件位置及大小的資訊, 請一步步看圖解。 step1. 建立新的專案。 圖1 ? step2. 選 C#類別庫, 按下一步。 圖2 ? step3. 設定新的專案, 並按建立。 圖3 ? step4. 設計程式碼TSystem.cs。
//----------------------------------------------------------------------
//動態程式庫 TSystem.dll 範例
//---------------------------------------------------------------------- using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using System.Drawing; namespaceTSystem
{
public class WindowPosition
{
//---------------------------------------------------------------------
public void WriteSystemInfo(string FileName, Point position)
{
BinaryWriter WriteFile = new BinaryWriter(File.Open(FileName,
FileMode.Create));
WriteFile.Write(position.X);
WriteFile.Write(position.Y);
WriteFile.Close();
} //------------------------------------------------------------------------
public Point ReadSystemInfo(string FileName)
{
if(!File.Exists(FileName))
return new Point(-1, -1);

BinaryReader ReadFile = new BinaryReader(File.Open(FileName,
FileMode.Open));
Point position = new Point(ReadFile.ReadInt32(),
ReadFile.ReadInt32());
ReadFile.Close();

return position;
} } //public class WindowPosition //-------------------------------------------------------------------------
public class WindowhSize
{
//---------------------------------------------------------------------
public void WriteSystemInfo(string FileName, Size size)
{
BinaryWriter WriteFile = new BinaryWriter(File.Open(FileName,
FileMode.Create)); //main form size
WriteFile.Write(size.Width);
WriteFile.Write(size.Height);
WriteFile.Close();
}

//------------------------------------------------------------------------
public Size ReadSystemInfo(string FileName)
{
if(!File.Exists(FileName))
return new Size(-1, -1);

BinaryReader ReadFile = new BinaryReader(File.Open(FileName,
FileMode.Open));
Size size = new Size(ReadFile.ReadInt32(), ReadFile.ReadInt32());
ReadFile.Close();

return size;
} } //public class WindowSize
} //namespace TSystem step5. 建置方案, 產生TSystem.dll。 圖4 ? step6. 產生的TSystem.dll的檔案及路徑。 圖5 ? step7. 主程式呼叫TSystem.dll, 需將產生的TSystem.dll加入參考。 圖6 ? step8. 主程式呼叫TSystem.dll( 關注//Note的地方即可 )。
//----------------------------------------------------------------------
//C# 主程式呼叫動態程式庫 TSystem.dll 範例
//----------------------------------------------------------------------
using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging; using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using Emgu.CV.Util;
using Emgu.Util;
using Emgu.CV.UI;
using Emgu.CV.BgSegm;
using Emgu.CV.VideoSurveillance; //Note
using TSystem;
using TCamera; //-----------------------------------------------------------------------------
namespace VT
{
public partial class MainForm : Form
{
//---------------------------------------------------------------------
public ToolboxForm CreateToolboxForm(Form parent, string text,
bool bshow = true)
{
ToolboxForm toolboxForm;
toolboxForm = new ToolboxForm();
toolboxForm.MdiParent = parent;
toolboxForm.Text = text; if(bshow)
toolboxForm.Show();

return toolboxForm;
}

//---------------------------------------------------------------------
public ImageXYForm CreateImageXYForm(Form parent, int number,
stringtext, bool bshow = true)
{
ImageXYForm imageForm;
imageForm = new ImageXYForm(number);
imageForm.MdiParent = parent;
imageForm.Text = text;

if(bshow)
imageForm.Show();

return imageForm;
}

//---------------------------------------------------------------------
public static MainForm _gmainForm = null;
public static ToolboxForm _gtoolboxForm = null;
public static ImageXYForm _gimageXYForm = null;

//Note
public WindowhSize _winSize = null;

//---------------------------------------------------------------------
//Main Program
//---------------------------------------------------------------------
public MainForm()
{
InitializeComponent();
}

//---------------------------------------------------------------------
private void MainForm_Load(objectsender, EventArgs e)
{
_gmainForm = this;

//Note
//讀取系統設定檔
_winSize = new WindowhSize();
Size size = _winSize.ReadSystemInfo(@"..\..\system\mainform.inf");
if(size.Width == -1 && size.Height == -1)
this.ClientSize = new Size(1200, 700);
else
this.ClientSize = new Size(size.Width, size.Height);

//修改mdi窗体背景色--------------------------------------------------------
MdiClient ctlMDI;

// Loop through all of the form's controls looking
foreach(Control ctl in this.Controls)
{
try
{
// Attempt to cast the control to type MdiClient.
ctlMDI = (MdiClient) ctl;

// Set the BackColor of the MdiClient control.
ctlMDI.BackColor = Color.LightGray; //this.BackColor; //Color.Blue;
}
catch(InvalidCastException)
{
// Catch and ignore the error if casting failed.
}
}

_gtoolboxForm = CreateToolboxForm(this, "工具箱");
_gimageXYForm = CreateImageXYForm(this, 0, "XY軸攝影機");
} //private void MainForm_Load(object sender, EventArgs e)

//--------------------------------------------------------------------- private void MainForm_FormClosed(object sender,
FormClosedEventArgs e)
{
//Note
_winSize.WriteSystemInfo(@"....\system\mainform.inf",
new Size(this.ClientSize.Width, this.ClientSize.Height));
}
} //public partial class MainForm : Form
} //namespace VT step9. 執行主程式成功。
圖7 ?


原文網址 石小川
2020-03-06 15:23:51

時常有學員問我PyQt5授權問題, 在這裡就一起回答同學的提問。

PyQt是GPLv3協議,大意是你的程式中使用了它,你的程式就要開源,如果閉源商用就會違反協議。

老師上課都開源程式碼故無此問題,但有同學是寫套裝商用軟體販售的,商用無法開源,就需要付可觀的授權費,這時用PyQt就麻煩了!

有沒有解套方式? 沒關係,直接換PySide2就好, 兩者API幾乎一樣, PySide2是由Qt官方維護,而PyQt5由非Qt官方維護。 而且未來發展應會超越PyQt5。

PySide是LGPL協議,如果你只是作為程式庫用它,你的程式還是可以閉源商用。所以很多人喜歡PySide,而且PySide2版本已支援Qt5功能。

結論是: 如果不做商業項目,強烈建議使用PyQt5,資料多,穩定。需要開發閉源商用軟體的就用PySide2。

避免無謂的商業授權費干擾,下面連結很清楚可參考看看LGPL和GPL :

https://progressbar.tw/posts/97


原文網址 石小川
2020-03-03 10:56:04

VS2019拖拉元件寫程式步驟,請參考投影片說明(VS2019產生一個App.mht)。


原文網址 石小川
2020-03-03 10:52:38

上課學員對 Visual Studio 2019 產生視窗程式不熟悉時可參考以下步驟,這套工具很實用也簡單,足夠你發展強大的應用程式,值得同學花時間駕馭它。 步驟1 如圖1, 建立新的專案。 步驟2 如圖2, 選Windows Forms App(.NET Framework) 項目,並按下一步鍵。 步驟3 如圖3, 設定新的專案,並按建立鍵。 步驟4 拖拉元件寫程式,請參考 使用Visual Studio 2019 產生一個視窗程式的簡單教學 - II 投影片說明(VS2019產生一個App.mht)。 圖4是程式WindowsFormsApp1執行的樣子。 Form1.cs 程式如下, 大部份程式碼是VS自動產生的, 我只寫兩行。 usingSystem; usingSystem.Collections.Generic; usingSystem.ComponentModel; usingSystem.Data; usingSystem.Drawing; usingSystem.Linq; usingSystem.Text; usingSystem.Threading.Tasks; usingSystem.Windows.Forms; namespaceWindowsFormsApp1 { public partial class Form1: Form { public Form1() { InitializeComponent(); } private voidbutton1_Click(objectsender, EventArgs e) { richTextBox1.Text = "OK"; //自已加上 } private voidbutton2_Click(objectsender, EventArgs e) { Close(); //自已加上 } } }


原文網址 石小川
2020-03-01 19:04:55

程式可控制的參數例如圖像尺寸(ROI)、拍照、曝光時間、GAMMA、對比差、亮度、自定義LUT、鏡頭翻轉、RGB顏色增益、飽和度、銳度、彩色轉黑白、色溫校正、反色、9組十字線位置和顏色、觸發模式、幀率控制,有附SDK及C#、C++ Builder、Delphi、labView、QT5、VB、VC等範例可參考,對於喜歡寫自動控制程式的人來說非常方便。

usingSystem;

usingSystem.Collections.Generic;

usingSystem.ComponentModel;

usingSystem.Data;

usingSystem.Drawing;

usingSystem.Linq;

usingSystem.Text;

usingSystem.Threading.Tasks;

usingSystem.Windows.Forms;

usingSystem.Runtime.InteropServices;

usingSystem.Threading;

usingCameraHandle = System.IntPtr;

usingCKSDK;

usingCKAPI = CKSDK.CKSDKAPI;

namespacePlayer

{

public partial class mainwindow: Form

{

# regionvariable

protectedCameraHandle m_hCamera = IntPtr.Zero; // 句柄

protectedThread m_CapThread;

protected boolm_bExit = false;

protected uintm_uWidth = 0;

protected uintm_uHeight = 0;

doublem_CapFrameRate = 0;

doublem_DisFrameRate = 0;

# endregion

public mainwindow()

{

InitializeComponent();

CameraRefresh();

}

public voidCaptureThreadFunction()

{

stImageInfo ImageInfo = newstImageInfo();

CameraSdkStatus status = CameraSdkStatus.CAMERA_STATUS_SUCCESS;

IntPtr pRGBFrame = IntPtr.Zero;

uintDispFrameNum = 0;

intFrameTimeCur = 0;

intFrameTimeLast = 0;

FrameStatistic curFS = newFrameStatistic();

FrameStatistic lastFS = newFrameStatistic();

IntPtr pbyBuffer = IntPtr.Zero;

uintdRGBBufLen = 0;

CameraHandle hBuf = IntPtr.Zero;

CKAPI.CameraPlay(m_hCamera);

while(!m_bExit)

{

CKAPI.CameraGetFrameStatistic(m_hCamera, outcurFS);

if(FrameTimeCur != 0)

{

FrameTimeCur = Environment.TickCount;

intdeltime = FrameTimeCur - FrameTimeLast;

if(1000 <= deltime)

{

m_CapFrameRate = (double)(((double)curFS.iCapture - (double)lastFS.iCapture) * 1000.0) / deltime;

m_DisFrameRate = (double)DispFrameNum * 1000.0 / deltime;

lastFS = curFS;

FrameTimeLast = FrameTimeCur;

DispFrameNum = 0;

}

}

else

{

FrameTimeCur = Environment.TickCount;

FrameTimeLast = FrameTimeCur;

lastFS = curFS;

}

//获取 RAW 数据

status = CKAPI.CameraGetRawImageBuffer(m_hCamera, refhBuf, 1000);

if(status != CameraSdkStatus.CAMERA_STATUS_SUCCESS)

{

Thread.Sleep(5);

continue;

}

//获得图像缓冲区地址

pbyBuffer = CKAPI.CameraGetImageInfo(m_hCamera, hBuf, refImageInfo);

//获得经 ISP 处理的 RGB 数据

//////////////////////////////////

if(dRGBBufLen < (ImageInfo.iWidth * ImageInfo.iHeight * 4))

{

dRGBBufLen = (ImageInfo.iWidth * ImageInfo.iHeight * 4);

pRGBFrame = Marshal.AllocHGlobal(Convert.ToInt32(dRGBBufLen));

}

m_uWidth = ImageInfo.iWidth;

m_uHeight = ImageInfo.iHeight;

CKAPI.CameraGetOutImageBuffer(m_hCamera, refImageInfo, pbyBuffer, pRGBFrame);

DispFrameNum++;

//////////////////////////////////显示

CKAPI.CameraDisplay(m_hCamera, pRGBFrame, refImageInfo);

//释放由 CameraGetRawImageBuffer 获得的缓冲区

CKAPI.CameraReleaseFrameHandle(m_hCamera, hBuf);

}

CKAPI.CameraPause(m_hCamera);

}

private voidCameraRefresh()

{

// 清空设备combobox

this.comboBox_DeviceList.Items.Clear();

CameraSdkStatus status;

//tSdkCameraDevInfo[] tCameraDevInfoList;

intdevNum = 0;

status = CKAPI.CameraEnumerateDevice(refdevNum);

if(status != CameraSdkStatus.CAMERA_STATUS_SUCCESS)

return;

for(inti = 0; i < devNum; i++)

{

tDevEnumInfo devAllInfo;

// 获取设备信息

status = CKAPI.CameraGetEnumIndexInfo(i, outdevAllInfo);

if(status != CameraSdkStatus.CAMERA_STATUS_SUCCESS)

continue;

// 将设备昵称增加到combobox控件中。

this.comboBox_DeviceList.Items.Add(new string(devAllInfo.DevAttribute.acFriendlyName));

}

if(devNum > 0)

this.comboBox_DeviceList.SelectedIndex = 0;

}

private voidCameraSetting()

{

if(m_hCamera != IntPtr.Zero)

{

if(CKAPI.CameraSetActivePage(m_hCamera, emSettingPage.SETTING_PAGE_ALL, 0) != CameraSdkStatus.CAMERA_STATUS_SUCCESS)

return;

if(CKAPI.CameraCreateSettingPageEx(m_hCamera) != CameraSdkStatus.CAMERA_STATUS_SUCCESS)

return;

CKAPI.CameraShowSettingPage(m_hCamera, 1);

}

}

private boolCameraPlay()

{

// 先停止当前的播放,然后再打开新的播放设备

CameraStop();

intindex = this.comboBox_DeviceList.SelectedIndex;

if(index < 0)

return false;

// 初始化设备,返回设备句柄

CameraSdkStatus status = CKAPI.CameraInit(refm_hCamera, index);

if(status != CameraSdkStatus.CAMERA_STATUS_SUCCESS)

{

m_hCamera = IntPtr.Zero;

return false;

}

// 初始化播放显示,设置显示图像的控件句柄

status = CKAPI.CameraDisplayInit(m_hCamera, this.pictureBox.Handle);

if(status != CameraSdkStatus.CAMERA_STATUS_SUCCESS)

{

CKAPI.CameraUnInit(m_hCamera);

m_hCamera = IntPtr.Zero;

return false;

}

// 新建视频播放线程

m_bExit = false;

m_CapThread = newThread(newThreadStart(CaptureThreadFunction));

m_CapThread.Start();

return true;

}

private voidCameraStop()

{

// 先关闭线程

if(m_CapThread != null)

{

m_bExit = true;

while(m_CapThread.IsAlive)

Thread.Sleep(10);

m_CapThread = null;

}

// 关闭相机句柄

if(m_hCamera != IntPtr.Zero)

{

CKAPI.CameraUnInit(m_hCamera);

m_hCamera = IntPtr.Zero;

}

}

private voidbutton_Refresh_Click(objectsender, EventArgs e)

{

CameraRefresh();

}

private voidbutton_PlayOrStop_Click(objectsender, EventArgs e)

{

if(this.button_PlayOrStop.Text == "Play")

{

if(CameraPlay())

{

this.button_PlayOrStop.Text = "Stop";

this.button_Setting.Enabled = true;

this.timer_DevInfo.Start();

}

}

else

{

CameraStop();

this.button_PlayOrStop.Text = "Play";

this.button_Setting.Enabled = false;

this.timer_DevInfo.Stop();

}

}

private voidbutton_Setting_Click(objectsender, EventArgs e)

{

CameraSetting();

}

private voidtimer_DevInfo_Tick(objectsender, EventArgs e)

{

this.label_DevInfo.Text = string.Format("resolution: {0} x {1} | capture frame rate: {2:###.##} | display frame rate: {3:###.##}",

m_uWidth, m_uHeight, m_CapFrameRate, m_DisFrameRate);

}

private voidForm1_FormClosing(objectsender, FormClosingEventArgs e)

{

CameraStop();

}

}

}

翻譯年糕


原文網址 石小川
2020-02-27 09:48:13

ROS 是機器人作業系統(Robot Operating System)的縮寫,ROS從2007發展至今已開始茁壯,目前很多機器人公司將旗下產品移植至ROS上,預見將來機器人工程師一定要會ROS技能。

ROS內建很多演算法如SLAM (Simultaneous Localization and Mapping)及 AMCL(Adaptive Monte Carlo Localization),以及包含很多軟體驅動接口很容易串接光學雷達、感測器、影像辨識、Arduino、Raspberry Pi、IO模組、運動卡等硬體元件,對建構自主導航機器人幫助很大,

下面連結網址是ROS安裝的方法及下載,有Windows和Ubuntu版本,對機器自動化有興趣的朋友可參考看看。

在Windows系统安装ROS 機器人作業系統 :
https://blog.csdn.net/ZhangRelay/article/details/82899582

在Linux系统安装ROS 機器人作業系統
https://makerpro.cc/2018/12/ros-setup-tutorial/

ROS.org :
http://wiki.ros.org/ROS/Installation

曾希哲
2020-02-27 10:06:09

ROS是現在進行式了

Chen Sheng Shou
2020-02-27 10:17:51

謝謝

Allen Tzeng
2020-02-27 10:43:28

最近剛接觸SLAM,想要實現卻不知如何下手


 

全不選 發文排行