C++11 在各平台下如何實現?

本篇簡單介紹 C++11 在各平台下如何實現,
C++11其實它是個標準,定義出通用標準的api接口,在各平台下各編譯器各自實作,以答到標準,

類似工業標準 大家制定好規範,各家去實現該功能,

由於該標準的一些功能在各平台下,大多有已經有各自的實作了,例如:std::thread, std::mutex, std::condition_variable,所以基本只是將這些接口在各平台下轉換成該平台的對應的接口就可以了,

舉例,在 LLVM 原始碼裡頭可以發現 std::thread 建立一條 thread 在 unix 平台下是靠 pthread 的 pthread_create 去實作,在 windows 平台下則是靠 _beginthreadex
所以其實可以想成 C++11 的 thread 是多了一層封裝,當然還有加上一些 C++ 好用的特性,

以下整理出各平台的對應api,對於 LLVM 原始碼是如何在各平台實作可以參考下方的相關連結。

std::thread unix windows
std::thread pthread_create _beginthreadex
std::thread::join pthread_join WaitForSingleObjectEx
std::thread::detach pthread_detach
std::thread::get_id pthread_self GetCurrentThreadId
std::thread::yield sched_yield SwitchToThread
std::this_thread::sleep_for nanosleep Sleep
std::mutex
std::mutex::lock pthread_mutex_lock AcquireSRWLockExclusive
std::mutex::unlock pthread_mutex_unlock LeaveCriticalSection
std::condition_variable
std::condition_variable::notify_one pthread_cond_signal WakeConditionVariable
std::condition_variable::notify_all pthread_cond_broadcast WakeAllConditionVariable
std::condition_variable::wait pthread_cond_wait SleepConditionVariableSRW

參考資源
從 pthread 轉換到 std::thread
https://www.cntofu.com/book/46/linux_system/cong_pthread_zhuan_huan_dao_std__thread.md
C++ 11是如何封裝Thread庫的?
https://www.zhihu.com/question/30553807
C++並發編程實戰-讀書簡記
http://lanbing510.info/2017/09/29/Cpp-Concurrency-In-Action.html
第 7 章 並行與並發 - 現代 C++ 教程: 高速上手 C++ 11/14/17/20
https://changkun.de/modern-cpp/zh-cn/07-thread/index.html

相關主題
std::thread 怎麼實作的?
std::condition_variable 怎麼實作的?
std::mutex 怎麼實作的?
C++11 在各平台下如何實現?

std::mutex 怎麼實作的?

本篇介紹一下一般各個作業系統的 C++ 編譯器是怎麼實作 std::mutex 的。

接下來我們來 trace llvm 的 libc++ 是怎麼實作 std::mutex 的。

1. std::mutex::lock 的實作

lock 轉換成內部的 __libcpp_mutex_lock

libcxx/src/mutex.cpplink
1
2
3
4
5
6
7
void
mutex::lock()
{
int ec = __libcpp_mutex_lock(&__m_);
if (ec)
__throw_system_error(ec, "mutex lock failed");
}

1-1. std::mutex::lock 在 unix 平台的實作內容

__libcpp_mutex_lock 在 unix 平台是呼叫 pthread_mutex_lock

libcxx/include/__threading_supportlink
1
2
3
4
int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
{
return pthread_mutex_lock(__m);
}

1-2. std::mutex::lock 在 windows 平台的實作內容

__libcpp_mutex_lock 在 windows 平台是呼叫 AcquireSRWLockExclusive

libcxx/src/support/win32/thread_win32.cpplink
1
2
3
4
5
int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
{
AcquireSRWLockExclusive((PSRWLOCK)__m);
return 0;
}

2. std::mutex::unlock 的實作

unlock 轉換成內部的 __libcpp_mutex_unlock

libcxx/src/mutex.cpplink
1
2
3
4
5
6
7
void
mutex::unlock() _NOEXCEPT
{
int ec = __libcpp_mutex_unlock(&__m_);
(void)ec;
_LIBCPP_ASSERT(ec == 0, "call to mutex::unlock failed");
}

2-1. std::mutex::unlock 在 unix 平台的實作內容

__libcpp_mutex_unlock 在 unix 平台是呼叫 pthread_mutex_unlock

libcxx/include/__threading_supportlink
1
2
3
4
int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
{
return pthread_mutex_unlock(__m);
}

2-2. std::mutex::unlock 在 在 windows 平台的實作內容

__libcpp_mutex_unlock 在 windows 平台是呼叫 ReleaseSRWLockExclusive

libcxx/src/support/win32/thread_win32.cpplink
1
2
3
4
5
int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
{
ReleaseSRWLockExclusive((PSRWLOCK)__m);
return 0;
}

總結

在一番 trace code 的結果後,std::mutex 在 llvm 的 libc++ 實作是這樣的,
在 unix 下
std::mutex::lock 轉換成 pthread_mutex_lock
std::mutex::unlock 轉換成 pthread_mutex_unlock
在 windows 下
std::mutex::lock 轉換成 AcquireSRWLockExclusive
std::mutex::unlock 轉換成 ReleaseSRWLockExclusive

相關主題
C/C++ 新手入門教學懶人包
std::thread 怎麼實作的?
std::condition_variable 怎麼實作的?
C++11 在各平台下如何實現?

std::condition_variable 怎麼實作的?

本篇介紹一下一般各個作業系統的 C++ 編譯器是怎麼實作 std::condition_variable 的。

接下來我們來 trace llvm 的 libc++ 是怎麼實作 std::condition_variable 的。

1. std::condition_variable::notify_one 的實作

notify_one 轉換成內部的 __libcpp_condvar_signal

libcxx/src/condition_variable.cpplink
1
2
3
4
5
void
condition_variable::notify_one() _NOEXCEPT
{
__libcpp_condvar_signal(&__cv_);
}

1-1. std::condition_variable::notify_one 在 unix 平台的實作內容

__libcpp_condvar_signal 在 unix 平台是呼叫 pthread_cond_signal

libcxx/include/__threading_supportlink
1
2
3
4
int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
{
return pthread_cond_signal(__cv);
}

1-2. std::condition_variable::notify_one 在 windows 平台的實作內容

__libcpp_condvar_signal 在 windows 平台是呼叫 WakeConditionVariable

libcxx/src/support/win32/thread_win32.cpplink
1
2
3
4
5
int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
{
WakeConditionVariable((PCONDITION_VARIABLE)__cv);
return 0;
}

2. std::condition_variable::wait 的實作

wait 轉換成內部的 __libcpp_condvar_wait

libcxx/src/condition_variable.cpplink
1
2
3
4
5
6
7
8
9
10
void
condition_variable::wait(unique_lock<mutex>& lk) _NOEXCEPT
{
if (!lk.owns_lock())
__throw_system_error(EPERM,
"condition_variable::wait: mutex not locked");
int ec = __libcpp_condvar_wait(&__cv_, lk.mutex()->native_handle());
if (ec)
__throw_system_error(ec, "condition_variable wait failed");
}

2-1. std::condition_variable::wait 在 unix 平台的實作內容

__libcpp_condvar_wait 在 unix 平台是呼叫 pthread_cond_wait

libcxx/include/__threading_supportlink
1
2
3
4
int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
{
return pthread_cond_wait(__cv, __m);
}

2-2. std::condition_variable::wait 在 windows 平台的實作內容

__libcpp_condvar_wait 在 windows 平台是呼叫 SleepConditionVariableSRW

libcxx/src/support/win32/thread_win32.cpplink
1
2
3
4
5
int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
{
SleepConditionVariableSRW((PCONDITION_VARIABLE)__cv, (PSRWLOCK)__m, INFINITE, 0);
return 0;
}

總結

在一番 trace code 的結果後,std::condition_variable 在 llvm 的 libc++ 實作是這樣的,
在 unix 下
std::condition_variable::notify_one 轉換成 pthread_cond_signal
std::condition_variable::wait 轉換成 pthread_cond_wait
在 windows 下
std::condition_variable::notify_one 轉換成 WakeConditionVariable
std::condition_variable::wait 轉換成 SleepConditionVariableSRW

相關主題
C/C++ 新手入門教學懶人包
std::thread 怎麼實作的?
std::mutex 怎麼實作的?
C++11 在各平台下如何實現?

Python 基礎教學目錄

本篇 Python 教學彙整了 ShengYu 過往學習 Python 的知識,在此整理成 Python 教學目錄以便日後的查詢與新手入門學習。

Python 基礎教學

這邊介紹一些 Python 常用的基礎知識與常用功能。
第一支 Python 程式
四則運算,加法、減法、乘法、除法用法與範例
print 格式化輸出
input 取得鍵盤輸入
if else elif 條件判斷 - if / if-else / if-elif-else 的用法
for 迴圈
while 迴圈
function 函式
str 字串
list 串列
set 集合
dict 字典
tuple 元組
range 用法
sort 排序
在 Python 寫 main 函式
sys.argv 用法
logging 日誌用法
lambda 運算式
三元運算子
and 運算子
or 運算子
not 運算子
xor 運算子

Python 字串處理

以下為 Python 字串處理的教學。
連接字串 join
字串分割 split
取代字元或取代字串 replace
去除空白與去除特殊字元 strip

Python 檔案處理

以下為 Python 檔案處理的教學。
讀取 txt 文字檔
寫入 txt 文字檔
讀取 csv 檔案
寫入 csv 檔案
讀取 json 檔案
寫入 json 檔案
讀取 ini 設定檔 ConfigParser 用法
寫入 ini 設定檔 ConfigParser 用法
讀取 yaml 檔案
寫入 yaml 檔案
判斷檢查檔案是否存在 os.path.isfile
判斷資料夾是否存在 os.path.isdir
判斷檢查路徑是否存在 exists
取得檔案大小 getsize
取出檔案名稱 basename
取出目錄的路徑 dirname

時間與日期

以下為 Python 時間與日期相關的教學。
取得系統當前時間
計算程式執行時間
使用 monotonic 計算程式執行時間
讓程式 sleep 延遲暫停時間
使用 datetime 日期相減

執行緒

以下為 Python 執行緒相關的教學。
建立多執行緒 thread
讓程式 sleep 延遲暫停時間

Python 物件導向 OOP

以下為 Python 物件導向相關的教學
類別 class
繼承 inheritance
多重繼承 multiple inheritance

演算法

以下為 Python 演算法相關的教學
sort 排序用法與範例
bubble sort 泡沫排序法
selection sort 選擇排序法

Python PIL 圖片處理系列文

使用 Python 搭配 PIL 模組作圖片處理的學習。
如何安裝PIL
讀取圖片並顯示
圖片模糊化 blur
圖片平滑化 smooth
旋轉圖片 rotate
水平翻轉、垂直翻轉圖片
裁切裁剪圖片 crop
縮放圖片 resize
製作圖片縮圖 thumbnail
在圖片上繪製文字
圖片貼上 paste
取得圖片Exif資訊

Python OpenCV 影像處理系列文

使用 Python 搭配 OpenCV 模組來作影像處理的學習。
Python 安裝 OpenCV 模組
彩色轉灰階(RGB/BGR to GRAY)
彩色轉HSV(RGB/BGR to HSV)
彩色轉YCbCr(RGB/BGR to YCbCr)
灰階轉彩色(Gray to RGB/BGR)
影像二值化 Image Thresholding
影像平滑模糊化 blur
影像邊緣偵測 Canny Edge Detection
垂直vconcat 和水平hconcat 影像拼接
圖片縮放 resize
顯示camera攝影機串流影像
讀取播放video影片檔案
儲存寫入video影片到檔案
影像侵蝕 erode 與影像膨脹 dilate

Python tkinter 視窗程式系列文

使用 Python 搭配 tkinter 模組來作視窗程式設計的學習。
tkinter Label 標籤用法與範例
tkinter Button 按鈕用法與範例
tkinter Entry 文字輸入框用法與範例
tkinter Combobox 用法與範例
tkinter OptionMenu 用法與範例
tkinter Canvas 用法與範例
tkinter messagebox 用法與範例
tkinter status bar 狀態列用法與範例
tkinter filedialog 開啟檔案對話框
tkinter filedialog.askdirectory 選擇資料夾對話框

Python PyQt5 視窗程式系列文

使用 Python 搭配 PyQt5 模組來作視窗程式設計的學習。
PyQt5 QLabel 標籤用法與範例
PyQt5 QPushButton 按鈕用法與範例
PyQt5 QLineEdit 文字輸入框用法與範例
PyQt5 QComboBox 下拉式選單用法與範例
PyQt5 QRadioButton 單選框用法與範例
PyQt5 QCheckBox 複選框用法與範例
PyQt5 QVBoxLayout 垂直佈局用法與範例
PyQt5 QHBoxLayout 水平佈局用法與範例
PyQt5 QGridLayout 網格佈局用法與範例
PyQt5 QPixmap 用法與範例
PyQt5 QImage 用法與範例
PyQt5 QPainter 用法與範例
PyQt5 QThread 用法與範例
PyQt5 QTimer 定時器用法與範例
PyQt5 QMessageBox 用法與範例
PyQt5 QFileDialog 開啟檔案對話框

Web

以下為 Python Web 網頁相關的教學。
快速建立簡單網頁伺服器 http websever
建立簡單的 Tornado Web
Flask 建立簡單的網頁

網路通訊

以下為 Python Socket 網路通訊相關的教學。
Python Socket 網路通訊教學
Python TCP Server/Client 網路通訊程式
Python UDP Server/Client 網路通訊程式

Python sort 排序用法與範例

本篇介紹如何使用 Python sort 排序用法與範例,在寫 python 程式有時會用到 sort 排序,python 最常需要對 list 排序,如果不考慮自己寫一個排序法的話,其實可以用 python 內建提供的 sort 排序法,接下來的教學將介紹怎麼使用 python 來作 list 的排序 sort。

Python 提供兩種內建排序的函式分別是 sort()sorted(),這兩個函式用法差別在於 sort() 會直接修改原始的 list 並完成排序,sorted() 會回傳一個已排序的新 list。以下 Python 排序的用法範例將分幾部份介紹,

  • Python sort 升序/由小到大
  • Python sort 函式參數
  • Python sort 降序/由大到小
  • Python sorted 升序/由小到大
  • Python sorted 降序/由大到小
  • 按某列排序 sort by column

那我們就開始介紹 Python sort 排序吧!

Python sort 升序/由小到大

在 Python 中把一個未排序的 list 使用 sort 進行排序,預設會由小排到大(升序),
如果要由大排到小的話(降序),sort 參數請使用 reverse=True。
可以看出經過 sort 後,list1 裡的數據已經被修改成排序後的結果了。

python-sort.py
1
2
3
4
5
6
7
8
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

list1 = [4, 5, 8, 3, 7, 1, 2, 6, 10, 9]
print("before:", list1)
list1.sort()
print("result:", list1)
print("after :", list1)

結果如下:

1
2
3
before: [4, 5, 8, 3, 7, 1, 2, 6, 10, 9]
result: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
after : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Python sort 函式參數

以下為 Python sort 函式參數以及說明,

1
list.sort(cmp=None, key=None, reverse=False)

cmp︰ 指定一個比較函式的話,會使用該比較函式進行排序
key︰ 指定元素的某一列為key鍵值, 也就是按照元素的某一列來進行排序
reverse︰排序規則,reverse=True 降序,reverse=False 升序(預設)。

官方文件說明
list.sort() 的詳細細節請參考這裡

Python sort 降序/由大到小

Python sort 如果要由大排到小的話(降序),sort 參數請使用 reverse=True。

python-sort2.py
1
2
3
4
5
6
7
8
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

list1 = [4, 5, 8, 3, 7, 1, 2, 6, 10, 9]
print("before:", list1)
list1.sort(reverse=True)
print("result:", list1)
print("after :", list1)

結果如下:

1
2
3
before: [4, 5, 8, 3, 7, 1, 2, 6, 10, 9]
result: [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
after : [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]

Python sorted 升序/由小到大

python sorted 用法如下,回傳的是排序好(升序)的結果,原始數據並無被修改,

python-sorted.py
1
2
3
4
5
6
7
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

list1 = [4, 5, 8, 3, 7, 1, 2, 6, 10, 9]
print("before:", list1)
print("result:", sorted(list1))
print("after :", list1)

結果如下:

1
2
3
before: [4, 5, 8, 3, 7, 1, 2, 6, 10, 9]
result: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
after : [4, 5, 8, 3, 7, 1, 2, 6, 10, 9]

Python sorted 降序/由大到小

python sorted 用法如下,回傳的是排序好(降序)的結果,原始數據並無被修改,

python-sorted2.py
1
2
3
4
5
6
7
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

list1 = [4, 5, 8, 3, 7, 1, 2, 6, 10, 9]
print("before:", list1)
print("result:", sorted(list1, reverse=True))
print("after :", list1)

結果如下:

1
2
3
before: [4, 5, 8, 3, 7, 1, 2, 6, 10, 9]
result: [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
after : [4, 5, 8, 3, 7, 1, 2, 6, 10, 9]

按某列排序 sort by column

這邊要介紹在numpy二維陣列中怎麼按某列來排序,

python3-sorted-by-column.py
1
2
3
4
5
6
7
8
9
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import numpy as np

a = np.array([[7, 5, 9],
[4, 8, 6],
[1, 2, 3]])

print(a[a[:1].argsort()])

或者分開寫,像是這樣

1
2
idx_list=a[:1].argsort()
print(a[idx_list])

或使用內建的sorted, 並且使用lambda指定按第2列排序,
詳細內容可以參考Python官方文件排序的介紹 , student_tuples sort by age 的部份,

1
2
b = np.array(sorted(a, key=lambda x:x[1]))
print(b)

結果輸出如下,按照第2列來排順序,其他列的資料也跟著一起搬移了,

1
2
3
[[1 2 3]
[7 5 9]
[4 8 6]]

其他參考
Python List sort()方法 | 菜鸟教程
https://www.runoob.com/python/att-list-sort.html
Sw@y’s Notes: [Python]如何在Python排序(Python Sorting)
http://swaywang.blogspot.com/2012/05/pythonpythonpython-sorting.html
淺談 Python 的排序 - 兩大類的部落格
https://marco79423.net/articles/%E6%B7%BA%E8%AB%87-python-%E7%9A%84%E6%8E%92%E5%BA%8F/
Python中sort、sorted高級排序技巧_謝軍的博客-CSDN博客_pythonsorted原地
https://blog.csdn.net/hduxiejun/article/details/56495729
python - Sorting arrays in NumPy by column - Stack Overflow
https://stackoverflow.com/questions/2828059/sorting-arrays-in-numpy-by-column

其它相關文章推薦
如果你想學習 Python 相關技術,可以參考看看下面的文章,
Python 新手入門教學懶人包
Python 取得鍵盤輸入 input
Python if else elif 用法教學與範例
Python for 迴圈
Python 建立多執行緒 thread
Python 讀檔,讀取 txt 文字檔
Python PIL 讀取圖片並顯示
Python OpenCV resize 圖片縮放

Python 產生 random 隨機不重複的數字 list

本篇 ShengYu 將介紹如何使用 Python 產生 random 隨機亂數不重複的數字 list,在寫 python 程式有時會用到生成隨機不重複的數字 list,接下來介紹怎麼使用 python 的 random 模組來產生 random 隨機不重複的數字 list。

方法

最簡單的方法是生成的新數字存放在一個list裡,之後每生成的新數字去檢查有沒有已經存在list裡。效能不會太好,因為要檢查的list會變長。
另一種方法是產生從 1~n 的一個數字 list,並打亂該 list,然後迭代 list 以獲得您的下一個不重複的隨機數字。

範例1:先建立一個 list, 再打亂該 list

先產生一個數字list,也可以用 range() 來產生數字list,
使用 random 模組裡的 shuffle() 來打亂該 list,
這邊要注意的是原來list的內容會被改變。

python-random-shuffle.py
1
2
3
4
5
6
7
8
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import random

list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print("list :", list1)
random.shuffle(list1)
print("result:", list1)

結果如下:

1
2
list  : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
result: [4, 5, 8, 3, 7, 1, 2, 6, 10, 9]

範例2:使用內建提供的產生不重複list的函式

random 模組裡已經有提供 sample() 來產生不重複的 list,
sample(aaa-list, k),從 aaa-list 裡回傳長度為 k 的 list

python-random-sample.py
1
2
3
4
5
6
7
8
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import random

list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print("list :", list1)
list2 = random.sample(list1, len(list1))
print("result:", list2)

結果如下:

1
2
list  : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
result: [10, 3, 2, 1, 5, 4, 7, 6, 8, 9]

官方文件說明
random 的詳細細節請參考這裡

延伸閱讀:Python random.randint 產生隨機數字

以上就是 Python 產生 random 隨機不重複的數字 list 介紹,
如果你覺得我的文章寫得不錯、對你有幫助的話記得 Facebook 按讚支持一下!

參考
https://blog.csdn.net/weixin_41770169/article/details/83306118
https://www.itread01.com/content/1543983002.html
http://tw.gitbook.net/t/python3/article-71.html

其它相關文章推薦
如果你想學習 Python 相關技術,可以參考看看下面的文章,
Python 新手入門教學懶人包
Python str 字串用法與範例
Python list 串列用法與範例
Python set 集合用法與範例
Python dict 字典用法與範例
Python tuple 元組用法與範例
Python 讀檔,讀取 txt 文字檔
Python 讓程式 sleep 延遲暫停時間
Python 計算程式執行時間
Python 建立多執行緒 thread

Python for 迴圈用法與範例

本篇介紹 Python for 迴圈的用法與範例,在寫 python 程式時重複性的事情就會使用到迴圈。Python for 迴圈的用法不難學,不過久久來寫 python 也是會忘,跟 while 迴圈相比 for 迴圈常用於確定的迴圈次數,接下來的教學將介紹如何使用 python 寫 for 迴圈。

基本的 for 迴圈寫法

Python 中 for 的用法如下,
sequence 可以是個串列 list元組 tuple字典 dict集合 set字串 strrange(),迴圈會在 sequence 裡的每個元素都迭代過一次完後才會停止。

1
2
for <item> in <sequence> :
print(item)

使用範例

range(5) 會產生一個 0~4 的 list,寫法等同於下個範例 array = [0, 1, 2, 3, 4],range 的詳細用法可以看這篇

python-for.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

for i in range(5):
print(str(i))

array = [0, 1, 2, 3, 4]
for i in array:
print(i)

fruits = ['apple', 'banana', 'orange']
for i in fruits:
print(i)

fruits = ['apple', 'banana', 'orange']
for i in range(len(fruits)):
print(fruits[i])

# 反轉
fruits = ['apple', 'banana', 'orange']
for i in reversed(fruits):
print(i)

結果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
0
1
2
3
4
0
1
2
3
4
apple
banana
orange
apple
banana
orange
orange
banana
apple

下一篇將介紹 while 迴圈的用法

參考
[1] Python for 循环语句 | 菜鸟教程
https://www.runoob.com/python/python-for-loop.html
[2] 常見 python for loop 迴圈寫法 - Python 教學筆記本
http://python-learnnotebook.blogspot.com/2018/10/python-for-loop.html
[3] Python 初學第四講 — 迴圈 - ccClub - Medium
https://medium.com/ccclub/ccclub-python-for-beginners-tutorial-4990a5757aa6
[4] Python 初學疑惑:For 迴圈怎麼用? - Ming-jun - Medium
https://medium.com/@mingjunlu/understanding-for-loops-in-python-64dd993510ce

其它相關文章推薦
如果你想學習 Python 相關技術,可以參考看看下面的文章,
Python 新手入門教學懶人包
Python 取得鍵盤輸入 input
Python if else elif 用法教學與範例
Python str 字串用法與範例
Python list 串列用法與範例
Python set 集合用法與範例
Python dict 字典用法與範例
Python tuple 元組用法與範例
Python 讀檔,讀取 txt 文字檔
Python 字串分割 split
Python 取代字元或取代字串 replace
Python 讓程式 sleep 延遲暫停時間
Python PIL 讀取圖片並顯示
Python OpenCV resize 圖片縮放

Python OpenCV 垂直vconcat 和水平hconcat 影像拼接

本篇 ShengYu 將介紹如何使用 Python 搭配 OpenCV 來作 vconcat 垂影像拼接跟 hconcat 水平影像拼接,在做影像處理時有時會需要把兩張圖片拼在一起,或兩張影像以上的拼接,接下就來介紹怎麼使用 python 搭配 OpenCV 的 cv2.vconcat 與 cv2.hconcat 來作影像拼接。

垂直影像拼接 vconcat

這個範例示範垂直影像拼接,將lena.jpg讀進來之後,使用 cv2.vconcat 將兩張影像垂直地拼接起來。

opencv-vconcat.py
1
2
3
4
5
6
7
8
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import cv2

image = cv2.imread("lena.jpg")
image_v = cv2.vconcat([image, image])
cv2.imshow("Result", image_v)
cv2.waitKey(0)

結果如下圖所示:

水平影像拼接 hconcat

這個範例示範水平影像拼接,將 lena.jpg 讀進來之後,使用 cv2.hconcat 將兩張影像水平地拼接起來。

opencv-hconcat.py
1
2
3
4
5
6
7
8
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import cv2

image = cv2.imread("lena.jpg")
image_h = cv2.hconcat([image, image])
cv2.imshow("Result", image_h)
cv2.waitKey(0)

結果如下圖所示:

補充說明

另外使用 np.tile 也可以達到同樣效果。

參考
[1] Concatenate images with Python, OpenCV (hconcat, vconcat, np.tile) | note.nkmk.me
https://note.nkmk.me/en/python-opencv-hconcat-vconcat-np-tile/
[2] Python OPenCV 图片简单拼接 hconcat vconcat函数使用_人工智能_qq_31587389的博客-CSDN博客
https://blog.csdn.net/qq_31587389/article/details/85722429

其它相關文章推薦
如果你在學習 Python 或 OpenCV 影像處理相關技術,可以參考看看下面的文章,
Python OpenCV resize 圖片縮放
Python OpenCV 彩色轉灰階(RGB/BGR to GRAY)
Python OpenCV 彩色轉HSV(RGB/BGR to HSV)
Python OpenCV 彩色轉YCbCr(RGB/BGR to YCbCr)
Python OpenCV 影像邊緣偵測 Canny Edge Detection
Python OpenCV 顯示camera攝影機串流影像

Python OpenCV resize 圖片縮放

本篇將介紹如何使用 Python 搭配 OpenCV 來 resize 縮放圖片,在寫 python 影像處理程式時常常會用到 opencv cv2.resize 圖片縮放的功能,接下來介紹怎麼使用 python 搭配 OpenCV 模組來進行圖片縮放 resize。

使用範例

以下 python 範例 ShengYu 是將 lena.jpg 讀取進來後,使用 opencv cv2.resize 進行縮放,從原本的512x512大小縮放成256x256 的大小。

opencv-resize.py
1
2
3
4
5
6
7
8
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import cv2

image = cv2.imread('lena.jpg')
image = cv2.resize(image, (256, 256), interpolation=cv2.INTER_AREA)
cv2.imshow('Result', image)
cv2.waitKey(0)

結果如下圖所示:

參數說明

cv2.resize(src, dsize[, dst[, fx[, fy[, interpolation]]]])

interpolation 說明
INTER_NEAREST 最近鄰插值
INTER_LINEAR 雙線性插值(預設)
INTER_AREA 使用像素區域關係進行重採樣。它可能是圖像抽取的首選方法,因為它會產生無雲紋理(波紋)的結果。 但是當圖像縮放時,它類似於INTER_NEAREST方法。
INTER_CUBIC 4x4像素鄰域的雙三次插值
INTER_LANCZOS4 8x8像素鄰域的Lanczos插值

cv2.resize 參數的詳細細節請參考這裡

OpenCV cv2.resize 提供五種方式的結果比較

下面的例子將 cv2.resize 所提供的所有種類都使用看看,來互相比較之間的差異,
我們先 resize 縮小成 400x400 的大小 來比較看看,
例子中還使用了 matplotlib 的方式將有圖片一起呈現在同一個視窗內,關於 matplotlib 的使用可以看看這篇
其中 matplotlib 的 imshow 圖片是使用RGB排列方式,所以這邊我們將 opencv 的 BGR 排列作個轉換,
這樣在 matplotlib 上顏色顯示才會正確。

opencv-resize.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import cv2
from matplotlib import pyplot as plt

image = cv2.imread('lena.jpg')
img1 = cv2.resize(image, (400, 400), interpolation=cv2.INTER_NEAREST)
img2 = cv2.resize(image, (400, 400), interpolation=cv2.INTER_LINEAR)
img3 = cv2.resize(image, (400, 400), interpolation=cv2.INTER_AREA)
img4 = cv2.resize(image, (400, 400), interpolation=cv2.INTER_CUBIC)
img5 = cv2.resize(image, (400, 400), interpolation=cv2.INTER_LANCZOS4)

# BGR 轉 RGB
img0_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
img1_rgb = cv2.cvtColor(img1, cv2.COLOR_BGR2RGB)
img2_rgb = cv2.cvtColor(img2, cv2.COLOR_BGR2RGB)
img3_rgb = cv2.cvtColor(img3, cv2.COLOR_BGR2RGB)
img4_rgb = cv2.cvtColor(img4, cv2.COLOR_BGR2RGB)
img5_rgb = cv2.cvtColor(img5, cv2.COLOR_BGR2RGB)

# 或這樣轉也可以
#img1_rgb = img1[:,:,::-1]

titles = ['Original Image', 'INTER_NEAREST', 'INTER_LINEAR', 'INTER_AREA', 'INTER_CUBIC', 'INTER_LANCZOS4']
images = [img0_rgb, img1_rgb, img2_rgb, img3_rgb, img4_rgb, img5_rgb]
for i in range(6):
plt.subplot(2, 3, i+1)
plt.imshow(images[i])
plt.title(titles[i])
plt.xticks([]), plt.yticks([])
plt.show()

結果如下圖所示,從下列結果圖發現,使用 INTER_NEAREST 會有些微地鋸齒狀,在圖片中的帽緣與鏡子邊緣上的線條可以發現,
INTER_NEAREST 是最簡單的插值方法,且速度快,但也容易出現鋸齒的現象。

OpenCV cv2.resize 這五種方式在速度上的比較

由快到慢排序:INTER_NEAREST > INTER_CUBIC > INTER_LINEAR > INTER_AREA > INTER_LANCZOS4
這是以我的電腦的測試數據,每次跑的結果都不太一樣,但整體速度排序來說差不多,

1
2
3
4
5
INTER_NEAREST:  0.000447 seconds
INTER_LINEAR: 0.000673 seconds
INTER_AREA: 0.001684 seconds
INTER_CUBIC: 0.000482 seconds
INTER_LANCZOS4: 0.003038 seconds

總結

如果是要縮小圖片的話,通常 INTER_AREA 使用效果較佳。
如果是要放大圖片的話,通常 INTER_CUBIC 使用效果較佳,次等則是 INTER_LINEAR。
如果要追求速度的話,通常使用 INTER_NEAREST。

其它參考
opencv: 图像缩放(cv2.resize)_人工智能JNing-CSDN博客
https://blog.csdn.net/JNingWei/article/details/78218837
Python-OpenCV中的resize()函数 - Rogn - 博客园
https://www.cnblogs.com/lfri/p/10596530.html
OpenCV圖像縮放resize各種插值方式的比較
人工智能_pan_jinquan的博客-CSDN博客
https://blog.csdn.net/guyuealian/article/details/85097633

其它相關文章推薦
如果你在學習 Python 或 OpenCV 影像處理相關技術,可以參考看看下面的文章,
Python OpenCV 彩色轉灰階(RGB/BGR to GRAY)
Python OpenCV 彩色轉HSV(RGB/BGR to HSV)
Python OpenCV 彩色轉YCbCr(RGB/BGR to YCbCr)
Python OpenCV 影像邊緣偵測 Canny Edge Detection
Python OpenCV 顯示camera攝影機串流影像
Python OpenCV 垂直vconcat 和水平hconcat 影像拼接
Python 旋轉圖片 rotate
Python 圖片模糊化 blur
Python 新手入門教學懶人包
小專案 Python OpenCV 圖片轉字元圖畫

Python thread 建立多執行緒用法與範例

本篇 ShengYu 將介紹如何使用 Python 來建立多執行緒 multithread,多執行緒 multithread 是很常會用到的程式技能,接下來介紹怎麼使用 python 3 的 threading 模組來建立執行緒吧。

以下的 Python thread 執行緒用法與範例將分為這幾部分,

  • Python 單執行緒到多執行緒的思維
  • Python 建立多個執行緒的範例
  • Python 撰寫多執行緒的注意事項

那我們開始吧!

Python 單執行緒到多執行緒的思維

原本寫程式只會單執行緒從頭寫到尾,例如單執行緒做了 ABC 三件事,總共花了 3 秒,但如果 ABC 三件事的內容是互相不影響的,那改成多執行緒的寫法,同時開 3 個執行緒分別去執行A、B和C的話,可能總共只需要 1 秒呢!這麼厲害的技巧一定要學囉,馬上來學習吧!

Python 建立多個執行緒的範例

下範例是使用 Python 3 的threading.Thread()建立了三個執行緒,每次的寫法都不太一樣,分別為去執行 print_hello()print_hellowrold()print_hi()
print_hello()函式裡很簡單地印出3次的 Hello,並且間隔0.5秒印一次,
print_hellowrold()函式是根據帶入一個參數n去印,需要注意的是在threading.Thread()args 是要傳入一個tuple, 而tuple只有一個元素的寫法為 args = (3,) 這樣,需要另外加個逗號,
print_hi()函式為兩個參數。

另外依據 time.sleep() 參數給入的秒數,time.sleep() 函式暫停執行當前的執行緒,
如果行程裡只有單一條執行緒的話,等同於暫停執行整個行程。

python3-create-thread.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import threading
import time

def print_hello():
for i in range(3):
time.sleep(0.5)
print("Hello " + str(i))

def print_hellowrold(n):
for i in range(n):
time.sleep(0.5)
print("Hello world "+ str(i))

def print_hi(n, interval):
for i in range(n):
time.sleep(interval)
print("Hi "+ str(i))

t1 = threading.Thread(target = print_hello)
t2 = threading.Thread(target = print_hellowrold, args = (3,))
t3 = threading.Thread(target = print_hi,
args = (3, 0.2))
t1.start()
t2.start()
t3.start()

輸出結果如下所示:

1
2
3
4
5
6
Hi
Hi
Hello
Hi
Hello
Hello

另外開執行緒也可以不取得回傳變數直接執行,例如threading.Thread(target = print_hello).start()這樣寫,

threading 的詳細細節請參考這裡

Python 撰寫多執行緒的注意事項

多執行緒程式比單執行緒程式難撰寫,也難以維護跟除錯,因為多執行緒間的資源共享,可能會造成以下這些問題:

  • Race condition (競爭情況/競爭條件/競爭危害)
  • 死結 Deadlock - 當一個執行緒在無窮等待一個鎖時。
  • Livelock
  • Starvation (餓死/飢餓) - 一個行程取得不到 CPU 時間來完成工作。

以上就是 Python thread 建立多執行緒用法與範例介紹,
如果你覺得我的文章寫得不錯、對你有幫助的話記得 Facebook 按讚支持一下!

其他參考
Use PyQt’s QThread to Prevent Freezing GUIs – Real Python
https://realpython.com/python-pyqt-qthread/

其它相關文章推薦
如果你想學習 Python 相關技術,可以參考看看下面的文章,
Python 新手入門教學懶人包
Python 取得鍵盤輸入 input
Python if else elif 用法教學與範例
Python for 迴圈
Python sort 排序
Python 讀檔,讀取 txt 文字檔
Python 字串分割 split
Python 取代字元或取代字串 replace