從物理光波模型、透鏡設計、CMOS光電轉換、ISP、Codec、Transition Protocol、Display Driver、Display SoC 都略懂一些,根據一般 IC 的設計原則,整理一些常識性的分享。
演算法筆記
從物理光波模型、透鏡設計、CMOS光電轉換、ISP、Codec、Transition Protocol、Display Driver、Display SoC 都略懂一些,根據一般 IC 的設計原則,整理一些常識性的分享。
SVP (SVP4),才15鎂,手癢就買下去了,調一調參數大概歸類一下演算法
因為這樣又把許多以前的動畫翻出來看了一遍 XD…
壓縮時該選哪個? 看目的是要做什麼,基本上一句話: 開發用 QP ,觀賞用CRF
CRF 或 QP=0 都是 loseless 這邊就不討論了,也沒有什麼實用價值。基本上在相同的設定值下,CRF 的檔案大小會比較小,但這是在於 CRF > 25 (平均畫質) 以上才比較有價值,否則差異不大。
就 MEMC (Frame Rate Conversion) 演算法開發我還是習慣用QP=18,因為同樣用 CRF=18,可能在快速移動物體邊緣出現些許 blocky ,但這是 CRF 壓縮造成的,不是演算法瑕疵,尤其我們在斤斤計較的就是這些快速移動的區域。
同上一篇,但是把所有 search range 平行化到每個 work-item,結論是沒有比較快…
繼上一篇的OpenCL版本,速度快了不少,但是顯卡會 freeze ….修改 TDR Level 讓 driver可以跑久一點
KeyPath : HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\GraphicsDrivers KeyValue : TdrLevel ValueType : REG_DWORD ValueData : TdrLevelOff (0) - Detection disabled TdrLevelBugcheck (1) - Bug check on detected timeout, for example, no recovery. TdrLevelRecoverVGA (2) - Recover to VGA (not implemented). TdrLevelRecover (3) - Recover on timeout. This is the default value.
這裡假設左右眼兩張影像已經經過 rectification,在 epipolar line 上限制一個小範圍的search range用以加速,簡單用 SAD 計算最小的左右視差作為 disparity。
使用 middlebury 的 dataset,勉強可以看出深度,但畢竟不到 100 行的小品 code 所以品質很差XD。
作為使用不同 window size 計算 SAD的比較,下圖左是用較大 window size 的結果,較為密實但粗略,小的 window size 則是會有較精確的但易破碎的結果;
因此才有了 coarse to fine 的演算法策略,先計算大的 window size 或低解析度的影樣匹配,然後再重複用小的 window size在鄰近 disparity 位置搜尋精確解。
但是 coarse to fine 也有無法解決的地方,太強烈的 smooth 特性反而失去細節,舉例來說,位於半島型的突出小東西或獨立的細小物體 ( 下圖綠框部分 ) ,在這些 window 中,真正要比較差異的區域其實是很少的,只在 window 正中間一小塊,越是 coarse 的範圍看到其他的部份也越多, 結果易忽略細小的目標物,而收斂成適合周邊範圍的 disparity;造成一種「穿越」或「填補」的現象。 coarse layer 定義下來的 disparity 若離目標物深度很遠,在 fine layer 相鄰深度的 refine 就會失敗 ( coarse layer 就消失的東西救不回來 );許多論文靠著定義特殊的 label 或 segment 來區分這些小區塊做特別處理。Middlebury stereo Evaluation 上目前最好的效果算是這類方法。
後面附上 source code,使用 openCV library讀寫圖
一個很 tricky 的點跟 CPU 計算不一樣,這邊如果把 main.cpp 呼叫 kernel 的 devBy 全部換成 devBx,在 thread 數不超過顯卡 core 負荷時(也就是一個 round 可以跑完 kernel ),結果是不會變的。可以嘗試在大圖需要多個 round 才能跑完 kernel 時就會出錯。
其實因為所有 thread 同步 inplace filtering 寫入關係,當寫入任一點時其他點的 source 已經不會需要再用到,所以不會有 propagate 的問題
讀寫檔案使用 OpenCV,減少 memory access 次數所以 x 和 y 方向 filtering 分開
重點在於 shader code 必須是固定的,如果 filter kernel 一直改變,估計在 runtime 重新 compile shader 的時間會成為瓶頸。
#include <iostream> #include <opencv2/opencv.hpp> #include <opencv2/core/ocl.hpp> #include <time.h> using namespace cv; using namespace cv::ocl; int main(int argc, char** argv) { setUseOpenCL(1); printf("useCL %s\n", useOpenCL()?"true":"false"); Mat img = imread(argv[1]); UMat mImgSource, mImgSource2, mImgResult, mImgResult2, mImgResult3; img.copyTo(mImgSource); int ksize = 200; RNG rng; while (true) { clock_t t1 = clock(); add(mImgSource, UMat(mImgSource.size(), mImgSource.type(), Scalar( rng.uniform(0,50), rng.uniform(0,50), rng.uniform(0,50), rng.uniform(0,50) )), mImgSource2); boxFilter(mImgSource2, mImgResult, -1, Size(ksize, ksize)); boxFilter(mImgResult, mImgResult2, -1, Size(ksize, ksize)); resize(mImgResult2, mImgResult3, Size(), 0.5, 0.5); clock_t t2 = clock(); printf("%d %d\n", ksize, (int)(t2-t1)); imshow("img", mImgResult3); int key = waitKey(1); if (key > 0) break; } }