Abstract
參加了2018的世貿牙展,被稱呼宋醫師真的有點爽阿XD,一些心得分享
我不是這個產業的業務,也沒有看過任何廣告文宣,所有評價都是自以為是的主觀認知和猜測,但,有什麼技術參考是比這個更有客觀性的呢?XD
把口掃機品牌全部看完,其實原理就是目前很夯的 structured light 3D reconstruction.
閱讀全文〈2018台北世貿牙展 口掃機原理分析 Digital intraoral scanner algorithm〉
演算法筆記
參加了2018的世貿牙展,被稱呼宋醫師真的有點爽阿XD,一些心得分享
我不是這個產業的業務,也沒有看過任何廣告文宣,所有評價都是自以為是的主觀認知和猜測,但,有什麼技術參考是比這個更有客觀性的呢?XD
把口掃機品牌全部看完,其實原理就是目前很夯的 structured light 3D reconstruction.
閱讀全文〈2018台北世貿牙展 口掃機原理分析 Digital intraoral scanner algorithm〉
從物理光波模型、透鏡設計、CMOS光電轉換、ISP、Codec、Transition Protocol、Display Driver、Display SoC 都略懂一些,根據一般 IC 的設計原則,整理一些常識性的分享。
從被動的 Image based stereo matching,進化到今日的 structured light,雖然在 Microsoft Kinect 早已實現多年,但真正將其發揚光大的恐怕還是 Apple 的 iPhoneX,本文就一個半吊子副職業光電工程師 Lv.1 來用猴子聽得懂的方式概述
基本上就是主動打光在物體上,這個光的圖形是經過設計的,有利於辨識比對。所以有一台投影機( 可以想做是相機 )的影像是已知的,在另外一台相機找到相同的 pattern 就可以知道深度,所以我們又回到了 stereo matching和 Epipolar geometry
等等…猴子聽得懂的概述呢?
好回過頭來,看過水滴在平靜的水面嗎,或是當我們丟一顆石頭到湖水中,可以看到一圈漣漪。
遠場繞射的神奇之處,舉個例來說,我抓了一把石頭,往湖中一撒,
然後湖之女神看似雨滴散亂的漣漪卻漸漸相消與結合,成形一個愛心圖案。Wow!(實際上是需要坐飛機在高空,底下是平靜無浪的大海,同時撒下巨大質量的鐵球…這我們就不探討真實性了)
#include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <zlib.h> int main () { setmode(0, _O_BINARY); setmode(1, _O_BINARY); uLongf compressedBytes = 0; uLongf unCompressedBytes = 0; // read data size fread(&compressedBytes , sizeof(uLongf), 1, stdin); fread(&unCompressedBytes, sizeof(uLongf), 1, stdin); // allocate data container Bytef *compressedData = (Bytef*) malloc(compressedBytes); Bytef *unCompressedData = (Bytef*) malloc(unCompressedBytes); // read compressed data fread(compressedData, compressedBytes, 1, stdin); // decompress uncompress(unCompressedData, &unCompressedBytes, compressedData, compressedBytes); // write un-compressed data fwrite(unCompressedData, unCompressedBytes, 1, stdout); fflush(stdout); free(compressedData); free(unCompressedData); return 0; }
SVP (SVP4),才15鎂,手癢就買下去了,調一調參數大概歸類一下演算法
因為這樣又把許多以前的動畫翻出來看了一遍 XD…
function recursiveDeepClone(o) { var newO, i; if (typeof o !== 'object') { return o; } if (!o) { return o; } if ( Buffer.isBuffer(o) ) { let o2 = Buffer.alloc(o.length); o.copy(o2); return o2; } if ( o.constructor === Int8Array ) { newO = new Int8Array( o ); return newO; } if ( o.constructor === Uint8Array ) { newO = new Uint8Array( o ); return newO; } if ( o.constructor === Uint8ClampedArray ) { newO = new Uint8ClampedArray( o ); return newO; } if ( o.constructor === Int16Array ) { newO = new Int16Array( o ); return newO; } if ( o.constructor === Uint16Array ) { newO = new Uint16Array( o ); return newO; } if ( o.constructor === Int32Array ) { newO = new Int32Array( o ); return newO; } if ( o.constructor === Uint32Array ) { newO = new Uint32Array( o ); return newO; } if ( o.constructor === Float32Array ) { newO = new Float32Array( o ); return newO; } if ( o.constructor === Float64Array ) { newO = new Float64Array( o ); return newO; } if ( o.constructor === Array ) { newO = []; for (i = 0; i < o.length; i += 1) { newO[i] = recursiveDeepClone(o[i]); } return newO; } newO = {}; for (i in o) { newO[i] = recursiveDeepClone(o[i]); } return newO; }
壓縮時該選哪個? 看目的是要做什麼,基本上一句話: 開發用 QP ,觀賞用CRF
CRF 或 QP=0 都是 loseless 這邊就不討論了,也沒有什麼實用價值。基本上在相同的設定值下,CRF 的檔案大小會比較小,但這是在於 CRF > 25 (平均畫質) 以上才比較有價值,否則差異不大。
就 MEMC (Frame Rate Conversion) 演算法開發我還是習慣用QP=18,因為同樣用 CRF=18,可能在快速移動物體邊緣出現些許 blocky ,但這是 CRF 壓縮造成的,不是演算法瑕疵,尤其我們在斤斤計較的就是這些快速移動的區域。
#include <stdio.h> #include <stdlib.h> #include <png.h> int imgSizeX = 1920; int imgSizeY = 1080; int imgNum = 100; void writePNG(FILE *file, const char *img) { png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); png_set_compression_level(png_ptr, 9); png_infop info_ptr = png_create_info_struct( png_ptr ); png_init_io(png_ptr, file); setjmp( png_jmpbuf(png_ptr) ); png_set_IHDR(png_ptr, info_ptr, imgSizeX, imgSizeY, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); png_write_info(png_ptr, info_ptr); setjmp( png_jmpbuf(png_ptr) ); png_bytep *row_pointers = new png_bytep[imgSizeY]; for (int y=0; y < imgSizeY; y++) { row_pointers[y] = (png_byte*) &img[y*imgSizeX*3]; } png_write_image(png_ptr, row_pointers); setjmp( png_jmpbuf(png_ptr) ); png_write_end(png_ptr, NULL); delete [] row_pointers; }
#include <fcntl.h> #include <io.h> setmode(1, _O_BINARY);
example use in ffmpeg pipe encoding mode
a.exe | ffmpeg -f rawvideo -pixel_format rgb24 -video_size 1920x1080 -i - -pix_fmt yuv420p output.mp4
#include <stdio.h> // includes for setmode #include <fcntl.h> #include <io.h> int imgSizeX = 1920; int imgSizeY = 1080; int imgNum = 100; int main() { // change to binary stdout mode (avoid 0x0A be changed into 0x0D 0x0A) setmode(1, _O_BINARY); for (int i = 0; i < imgNum; ++i) { for (int y = 0; y < imgSizeY; ++y) { for (int x = 0; x < imgSizeX; ++x) { unsigned char color[3] = {0x00, (x+i*5) & 0xFF, 0x00}; fwrite(color, 1, 3, stdout); } } } fflush(stdout); return 0; }