2018年3月13日 星期二

實作代碼 如何切適當的分函式功能

實作代碼 如何切適當的分函式功能

寫了一個大專案之後整理的心得,隨著經驗的累積還會再更新。
寫程式的風格或許沒有最優解,有的只是不斷地採坑不斷地總結。
如果正好這一個風格適合多數人,而且確實效率好,那就是一份好方法。
這一份方法可以稱為高頻小套路,是讓一個新手高效率成長的最優解。

2018.03.13

一個好的流程架構最好的開發方法,先用別人的函式庫如OpenCV完成
然後開始拆分他的函式拆成可以理解的大功能ABC,然後分別單獨實作ABC
大功能ABC具有的特性是
    1. 各個都是大量運算
    2. 彼此之間傳遞的資料項目簡單,最好就int
(要找到大運算中間的休息點傳遞基本數值以便丟棄大物件,讓他在func內結束減少干擾)
    3. 到哪裡都可以運行
        然後這些ABD中的A裡面又有 abc 小項目

        abc小項目中需要有下面的特性
        1. 有明確的目標就是要幹嘛
        2. 只能完成一件事情
        3. abc組合起來是流程圖
        4. 每個都是可公開的 ADT
        5. 只能用物件當引數
        6. 可以容納,不知道該怎麼處理的髒代碼

            然後這些 abc 其中的 a 又有123小項目
            123 需要有下面特性
            1. 只為了做一件小事,代碼長度不超過1個 1080P 螢幕
            3. 避免使用物件當引數,拆解成基本型態
            4. 到哪裡都可以運行

2018年3月12日 星期一

opencv 特徵點匹配 ORB、SURF、SIFT 以及 RANSAC 過濾的範例代碼

opencv 特徵點匹配 ORB、SURF、SIFT 以及 RANSAC 過濾的範例代碼

void sift1(string name1, string name2){
    Mat img_1 = imread(name1, CV_LOAD_IMAGE_GRAYSCALE);
    Mat img_2 = imread(name2, CV_LOAD_IMAGE_GRAYSCALE);
    Mat img_matches;
    Mat img_test;

    if(!img_1.data || !img_2.data){
        cout << "opencv error" << endl;
        return;
    }

    // cv::Ptr<Feature2D> f2d = xfeatures2d::SIFT::create();
    // cv::Ptr<Feature2D> f2d = xfeatures2d::SURF::create();
    cv::Ptr<Feature2D> f2d = ORB::create();

    //-- Step 1: Detect the keypoints:
    std::vector<KeyPoint> keypoints_1, keypoints_2;
    f2d->detect(img_1, keypoints_1);
    f2d->detect(img_2, keypoints_2);

    img_test = img_1;
    drawKeypoints(img_1, keypoints_1, img_test, Scalar::all(-1));
    imshow("Keypoints", img_test);

    //-- Step 2: Calculate descriptors (feature vectors)    
    Mat descriptors_1, descriptors_2;
    f2d->compute(img_1, keypoints_1, descriptors_1);
    f2d->compute(img_2, keypoints_2, descriptors_2);

    //-- Step 3: Matching descriptor vectors using BFMatcher :
    BFMatcher matcher;
    std::vector< DMatch > matches;
    matcher.match(descriptors_1, descriptors_2, matches);
    drawMatches(img_1, keypoints_1, img_2, keypoints_2,
        matches, img_matches, Scalar::all(-1), Scalar::all(-1),
    std::vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
    imshow("Matches", img_matches);

    //-- Quick calculation of max and min distances between keypoints
    double max_dist = 0; double min_dist = 100;
    for(int i = 0; i < descriptors_1.rows; i++){
        double dist = matches[i].distance;
        if(dist < min_dist) min_dist = dist;
        if(dist > max_dist) max_dist = dist;
    }
    printf("-- Max dist : %f \n", max_dist);
    printf("-- Min dist : %f \n", min_dist);
    //-- Draw only "good" matches (i.e. whose distance is less than 3*min_dist )
    std::vector< DMatch > good_matches;
    for(int i = 0; i < descriptors_1.rows; i++){
        if(matches[i].distance < 3 * min_dist)
            good_matches.push_back(matches[i]);
    }
    drawMatches(img_1, keypoints_1, img_2, keypoints_2,
        good_matches, img_matches, Scalar::all(-1), Scalar::all(-1),
        std::vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
    imshow("Good Matches", img_matches);

    vector<DMatch>& Input_matches = matches; // good_matches, matches
    // get feat point
    vector<Point2f> featPoint1;
    vector<Point2f> featPoint2;
    for(size_t i = 0; i < Input_matches.size(); i++){
        //-- Get the keypoints from the good matches
        featPoint1.push_back(keypoints_1[Input_matches[i].queryIdx].pt);
        featPoint2.push_back(keypoints_2[Input_matches[i].trainIdx].pt);
    }
    // get Homography and RANSAC mask
    vector<char> RANSAC_mask;
    Mat Hog = findHomography(featPoint1, featPoint2, RANSAC, 3, RANSAC_mask, 2000, 0.995);
    drawMatches(img_1, keypoints_1, img_2, keypoints_2,
        Input_matches, img_matches, Scalar::all(-1), Scalar::all(-1),
        RANSAC_mask, DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
    imshow("RANSAC Matches", img_matches);

    waitKey(0);
}

2018年3月10日 星期六

Win10 ATI HD4850 4870 driver 正確運作 CCC 軟體

Win10 ATI HD4850 4870 driver 正確運作 CCC 軟體

先看結果 (右下角有當前時間)
AMD的官方已經直接表名說不支持不能用了,不過實際測試之後還是可以使用。
測試的系統是 Windwos10 1709,顯示卡有 HD4870 HD4855 HD4350 等三張。

安裝開始

要分開裝驅動與 catalyst control center 軟體

下載

要下載舊版的來用
目標下載 13.1 來使用
下載下來要先安裝
這個會先解壓縮到C曹的這個位置,先解壓縮(按上圖Install)
然後會跳出安裝選單如下圖,先不要按,重要的是目前已取得檔案等一下會用到。
到上圖這個畫面就先停著不要動

手動安裝驅動

打開工作管理員,快捷鍵是先按 Win+X 然後再按 M
選到剛剛的位置 (下面是預設)
C:\AMD\Support\13-1-legacy_vista_win7_win8_64_dd_ccc\Packages\Drivers\Display\W86A_INF
選中 C7 開頭的這個
然後就可以安裝了,安裝完成之後解析度就可以正常條了
要確認有沒有安裝可以查看驅動程式日期,13.1內附的驅動日期是2012.11,微軟提供的是2015版本的,要驅動CCC必須使用CCC內附的版本才可以。

CCC 驅動安裝

必須先安裝完驅動才可以,再來跳回來剛剛的CCC安裝介面可以按下一步了。
如果要開CCC,那驅動就要裝CCC附贈的同一個驅動版本。
這裡要選自訂然後取消驅動的打勾(因為剛剛已經安裝了)

(備註:我不是在同一台電腦做的,這台沒安裝卡,這裡才會不能取消打勾)
然後安裝完畢之後可能還會看不到,要重新啟動之後 CCC 開起來就可以調整細部選項了
比如說接上 HDMI 之後螢幕內縮編編有黑框,可以把縮放調為 0 就沒黑邊了
或者是接上 HDMI 之後顏色怪怪的偏白,也是驅動裡面調成全彩 RGB 就好了
經過測試後發現最新可安裝的版本為 13.4 版本,這個也可以順利驅動+開啟CCC,不過介面是英文版的。

2018年3月9日 星期五

Win10 一直自動清理縮圖,要重跑縮圖

Win10 一直自動清理縮圖,要重跑縮圖

貌似是更新到 1709 才這樣,我不確定是升級上還得bug還是全新安裝也會這樣,總而言之好像還蠻多人的,解決辦法只能停用這個功能。
1709之後多了自動清理緩存的功能,不過實際上如果SSD容量足夠並不建議時常清理,半年清理個一次就差不多了。

自動清理的設定位置

位置在 儲存空間 內,你可以直接在開始搜尋 儲存空間 就可以看到他
這個東西會自動清理,但是我已經將它關閉了,他還是不正常作用,時不時就給我清理一下,實在很惱人。
工作排程DiskCleanupSilentCleanup 強制關閉這個功能就會好了。
工作排程可以在開始欄打字搜尋找到。
找到他之後把它關閉吧,之後就不會再來煩你了~

Visual Studio IMAGE::BuildImage 錯誤

Visual Studio IMAGE::BuildImage

錯誤信息:
LINK : fatal error LNK1000: Internal error during 
IMAGE::BuildImage
先按上面的清除方案把暫存檔清掉,如果沒犯什麼引入的錯大概就好了
如果清掉還是不行,有可能是引入的問題
  1. A.cpp 引入 B.hpp 然後 B.cpp 又引入 A.hpp 互相卡住
  2. 盡量清除 .hpp 內的引入,寫到 .cpp 內
[1] 整理一下邏輯了,會互卡就很奇怪了~很容易出現在架構沒出來走一步算一步的情況
[2] 降低多餘的引用,如果寫在 hpp 內每個引用的檔案都會引用到
寫道 cpp 內的話需要置後,比如說一份檔案 A.hpp 內寫到了 vector ,那你在 A.cpp 的時候要這樣寫
#include <vector>
#include "A.hpp"
這樣就能編過了,不過也導致每個引入 A 的都要補 vector,如果是內建的比如說 vector、string 這些用到的機率也很高就寫吧;如果是自己寫的函式庫看有沒有方法,改個寫法避開,原則上能越少越好。

參考

2018年3月8日 星期四

Visutal studio 中的 git 同步失敗 Git failed with a fatal error

Visutal studio 中的 git 同步失敗

出現的訊息是這樣的:
在存放庫 C:\Users\hunan\source\repos\feat_fast 中於本機建立了認可 89194807
推送至遠端存放庫時發生錯誤: Git failed with a fatal error.
HttpRequestException encountered.
   �ǰe�n�D�ɵo�Ϳ��~�C
cannot spawn askpass: No such file or directory
could not read Username for 'https://github.com': terminal prompts disabled
Pushing to https://github.com/XXXX/ORB.git
我最後的解決辦法是開啟 git for windwos 中的 bash 然後 cd 到目錄位置,使用他來上傳
git push master origin
更新今天找到原因了,因為github改版了,在認證上有做調整
https://githubengineering.com/crypto-removal-notice/
VS是被引響到的範圍之一,更新VS到最新版本就好了,然後建議 git for windows 也更新一下到最新版。

參考

2018年3月7日 星期三

STM32F4 如何輕鬆的自訂 LED 任意腳位初始化 與 點亮

STM32F4 如何輕鬆的自訂 LED 任意腳位初始化 與 點亮

有鑑於官方預設語言是C,想要點亮LED要做的工作也是有點多行,寫個一兩個還不是什麼大事,寫個幾10個然後發現有錯要修改,就難過了。
前一陣子在PTT看到有人用 macro 在 C 上面弄出 STL ,仿物件實在很牛QuQ
雖然看不董細節怎麼做的,不過至少原理是解了的,依樣畫葫蘆刻了一個做練習
/**
  * @brief  LED initial Obj
  * @author None
  * @site   https://charlottehong.blogspot.tw/
  */
#define STATEMENT_(...)  do {__VA_ARGS__} while (0)
#define LED                                               \
struct HAL_LED{                                           \
  GPIO_TypeDef* port;                                     \
  uint16_t pin;                                           \
  GPIO_InitTypeDef  GPIO_InitStruct;                      \
}
#define GPIO_ENABLE(GPIO)                                 \
STATEMENT_(                                               \
  __HAL_RCC_##GPIO##_CLK_ENABLE();                        \
)
#define LED_init(self, GPIO, GPIO_PIN, state)             \
STATEMENT_(                                               \
  self.port=(GPIO);                                       \
  self.pin=(GPIO_PIN);                                    \
  __HAL_RCC_##GPIO##_CLK_ENABLE();                        \
                                                          \
  self.GPIO_InitStruct.Pin = self.pin;                    \
  self.GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;        \
  self.GPIO_InitStruct.Pull = GPIO_PULLUP;                \
  self.GPIO_InitStruct.Speed = GPIO_SPEED_FAST;           \
                                                          \
  HAL_GPIO_Init(self.port, &self.GPIO_InitStruct);        \
  HAL_GPIO_WritePin(self.port, self.pin, state);          \
)
#define LED_WritePin(self, state)                         \
STATEMENT_(                                               \
  HAL_GPIO_WritePin(self.port, self.pin, state);          \
)
#define LED_TogglePin(self)                               \
STATEMENT_(                                               \
  HAL_GPIO_TogglePin(self.port, self.pin);                \
)

使用範例

你可以在主程式新增一個仿物件
LED led1;
然後對著他初始化,就是設定角位(下面是設置成 PC4)
LED_init(led1, GPIOG, GPIO_PIN_2, GPIO_PIN_RESET );
GPIO_PIN_RESET 起始狀態是0
GPIO_PIN_SET 起始狀態是1
然後我們點亮他吧
LED_TogglePin(led1);
嗯就這麼簡單,要加函式在自己加~應該很容易能看懂