2017年10月6日 星期五

Windows10 多使用者,刪除桌面圖示其他使用者跟著被刪除

Windows10 多使用者,刪除桌面圖示其他使用者跟著被刪除

這個問題主要是因為有些軟體放置的捷徑路徑不是放在使用者內,而是放在公用資料夾內,有在注意的人看安裝訊息的人應該看過會讓你決定是要替所有使用者安裝,還是只替當前使用者安裝,這句話的意思就是要安裝到公用資料夾還是個人資料夾。
所有使用者的桌面或開始程式集裡面都會包含公用使用者
這就是問題所在拉~導致你在A使用者砍掉圖示之後B使用者開上圖示捷徑也跟著不見,解決就是去公用資料夾,把圖示移動到自己的桌面就好。
下面分別給當前使用者與公用使用者的路徑,路徑是相對直徑直接貼上即可自動對應到你的使用者名稱。
公用桌面:%SystemDrive%\Users\Public\Desktop
當前使用者桌面:%USERPROFILE%\Desktop

2017年10月4日 星期三

C / C++ 影像處理如何畫線與畫箭頭

C++ 影像處理如何畫線與畫箭頭

代碼關鍵函式要用點斜式,然後用for迴圈去跑x軸或y軸,跑完那一條線
struct ImgRaw{
    int width;
    int height;
    vector<unsigned char> raw_img;
};

void drawLine_p(ImgRaw& img, int y, int x, int y2, int x2, float val) {
    // 兩點之間的距離差
    float dx = static_cast<float>(x2-x);
    float dy = static_cast<float>(y2-y);
    // 以Y軸為主
    float sita=fastAtan2f(dy, dx);
    if (sita>45 and sita<135 or sita>225 and sita<315) {
        float slopeY = dx/dy; // 斜率
        for (int i = 0; i < abs(dy); i++) {
            int iFix = dy>0? i:-i;
            int currPos = static_cast<int>(iFix*slopeY+.5f + x);

            int distX = currPos;
            int distY = y+iFix;

            if (distX<0 or distX>=(int)img.width or distY<0 or distY>=(int)img.height) {
                return;
            }
            img.raw_img[distY*img.width + distX] = static_cast<unsigned char>(val);
        }
    } 
    // 以X軸為主
    else {
        float slopeX = dy/dx; // 斜率
        for (int i = 0; i < abs(dx); i++) {
            int iFix = dx>0? i:-i;
            int currPos = static_cast<int>(iFix*slopeX+.5 + y);

            int distX = x+iFix;
            int distY = currPos;

            if (distX<0 or distX>=(int)img.width or distY<0 or distY>=(int)img.height) {
                return;
            }
            img.raw_img[distY*img.width + distX] = (unsigned char)val;
        }
    }
}
然後角度的不一樣比如說45~90度跑Y軸會比較好,線連得比較密,如果是0~45度則是跑X軸比較好,才不會出現斷線。
角度的判斷計算使用。
float sita = fastAtan2f(dy, dx);
  • ImgRaw帶有圖像資訊、長、寬
  • fastAtan2f是從OpenCV複製出來的可以參考站內文這裡
接下來有了直線之後就是寫一個,輸入角度與長度的函式,簡單來說就是算出頭尾的位置然後帶入剛剛的函式畫線。
void drawLineRGB_s(ImgRaw& img, int y, int x, float line_len, float sg) {
        // 檢查
        if (line_len <= 0) { return; }
        // 算頭尾
        int x2 = x + line_len*cos(sg * M_PI/180);
        int y2 = y + line_len*sin(sg * M_PI/180);
        // 畫線
        drawLineRGB_p(img, y, x, y2, x2);
    }
再來箭頭就只是多話2條線,帶入剛剛的給點給角度的函式畫出箭頭
void draw_arrowRGB(ImgRaw& img, int y, int x, float line_len, float sg) {
        // 檢查
        if (line_len <= 0) { return; }
        // 算頭尾
        int x2 = x + line_len*cos(sg * M_PI/180);
        int y2 = y + line_len*sin(sg * M_PI/180);
        // 畫線
        drawLineRGB_p(img, y, x, y2, x2);
        // 畫頭
        drawLineRGB_s(img, y2, x2, 10, sg-150);
        drawLineRGB_s(img, y2, x2, 10, sg+150);
    }


如何使用

drawLine有兩個,一個是給定兩個點,把他們連起來,另一個是給定原點, 長度, 角度,也就是給極值的方式畫線。
    ImgRaw img_lineRGB(1280, 720);
    for (size_t i = 0; i < 36; i++) {
        Draw::draw_arrowRGB(img_lineRGB, 200, 200, 100.f*sqrt(2), i*10);
    } img_lineRGB.bmp("lineRGB.bmp");
ImgRaw 做的事情很簡單只是開一個 vector(1280*720*3) 然後儲存他的長1280和寬720
畫一圈的箭頭

原理

主要是利用斜率去算的,假設有兩個點,分別是 (0, 0) 與 (40,50) 斜率的公式,其中b是偏移量暫時不管她。
y=ax+b;
斜率就只是相減而已
dy=50-0;
dx=40-0;

m=dy/dx;
既然已知斜率那就用for迴圈去跑x的範圍 0~40 就可以得出y的位置了
不過這會遇到一個問題是當直線是上下的時候 for 迴圈跑的次數是0畫不出線,其次可以發現這種畫法當線條比較偏上的時候,45~135度的範圍會明顯斷線的感覺,因此這時候要變成以y為主,for迴圈去跑y反向計算出x。
這樣就可以畫出上圖比較好看一些的線條了。


範例程式

完整的程式參考:https://goo.gl/rAJLjH

atan() 和 atan2() 快速算法

atan() 計算的時候如何得知正確角度;fastAtan2f() 快速計算方法

atan() 在計算的時候是沒有把dx和dy的正負號考慮進去的,也就是說在第3象限的時候會被當作第一象限來處理。
解決方法很容易,有一個已經幫你處好的函式是 atan2() 可以直接輸入 atan2(dy, dx) 計算出正確的結果,不過出來的角度是 -PI~PI 逕度還需要處理一下轉為角度。
這裡提供一個已經處理好上述而且速度更快的方法,是來自於OpenCV內的函式原封不動複製出來的應該足夠安全。

atan2()

static inline float fastAtan2f(float dy, float dx){
    // 快速atan運算
    static const float atan2_p1 = 0.9997878412794807f*(float)(180/M_PI);
    static const float atan2_p3 = -0.3258083974640975f*(float)(180/M_PI);
    static const float atan2_p5 = 0.1555786518463281f*(float)(180/M_PI);
    static const float atan2_p7 = -0.04432655554792128f*(float)(180/M_PI);
    static const float atan2_DBL_EPSILON = 2.2204460492503131e-016;

    float ax = std::abs(dx), ay = std::abs(dy);
    float a, c, c2;
    if (ax >= ay) {
        c = ay/(ax + static_cast<float>(atan2_DBL_EPSILON));
        c2 = c*c;
        a = (((atan2_p7*c2 + atan2_p5)*c2 + atan2_p3)*c2 + atan2_p1)*c;
    } else {
        c = ax/(ay + static_cast<float>(atan2_DBL_EPSILON));
        c2 = c*c;
        a = 90.f - (((atan2_p7*c2 + atan2_p5)*c2 + atan2_p3)*c2 + atan2_p1)*c;
    }
    if (dx < 0)
        a = 180.f - a;
    if (dy < 0)
        a = 360.f - a;
    return a;
}
fastAtan2f() 計算出來就是 0~360 度的角度了,如果需要逕度從代碼內把轉換的移除即可。
M_PI 可能需要自己定義一下,或者引入cmath並啟用宏定義(啟用是一行宏定義的代碼需要再自己查)。
如果只是單單需要拍自己定一個比較快~
#define M_PI 3.14159265358979323846

atan()

這個OpenCV裡面就沒有,不過可以從上面的 atan2() 修改一下即可(簡單來說就是x設定成1)。
這個比較常用到逕度版本的我貼逕度版本的
float fastAtanf_rad(float dy){
    static const float atan2_p1 =  0.9997878412794807f;
    static const float atan2_p3 = -0.3258083974640975f;
    static const float atan2_p5 =  0.1555786518463281f;
    static const float atan2_p7 = -0.04432655554792128f;
    static const float atan2_DBL_EPSILON = 2.2204460492503131e-016;

    float ax = 1.0, ay = std::abs(dy);
    float a, c, c2;
    if (ax >= ay) {
        c = ay/(ax + static_cast<float>(atan2_DBL_EPSILON));
        c2 = c*c;
        a = (((atan2_p7*c2 + atan2_p5)*c2 + atan2_p3)*c2 + atan2_p1)*c;
    } else {
        c = ax/(ay + static_cast<float>(atan2_DBL_EPSILON));
        c2 = c*c;
        a = M_PI*0.5 - (((atan2_p7*c2 + atan2_p5)*c2 + atan2_p3)*c2 + atan2_p1)*c;
    }

    if (dy < 0)
        a = - a;

    return a;
}
這一分我有做簡單的驗證是沒問題的,可以參照底下的代碼有過程,敏感場合建議自己在想方法驗證一次~

其他

全部一共4個版本,atan()和atan2() 以及他們的 逕度版本與角度版本。

2017年9月29日 星期五

電腦休眠睡眠之後莫名其妙或動到滑鼠自己喚醒

電腦休眠睡眠之後莫名其妙或動到滑鼠自己喚醒


很多時候之所以不關電腦僅僅只是因為這樣方便,開啟的程序在明天之後又可以直接開始,其實也不用這麼特別費電,除非是需要連網的程式,不然使用休眠或睡眠就可幫你保持當前狀態,並且關閉電腦。
睡眠跟休眠差異不大,差異在於睡眠不會將記憶體斷電,記憶體一旦斷電資料就全沒了,所以睡眠的喚醒速度會快很多;但是如果遇到停電,比如說把插頭拔掉,那麼記憶體的東西就全沒,會變成休眠狀態記憶體的副本在你進入睡眠的時候會移併複製一份;比較簡單的分辨方法就是電源燈與硬碟燈會慢速閃爍。
至於更古老以前的XP所有的待機那又是另一回事。
新版的Win10已經沒有休眠這個選項了,剛剛也有提到其實睡眠也包含休眠,不過如果是在自己的房間睡覺的時候一閃一閃的也是很受不了。
要開啟休眠可以到控制台的電源選項
然後可以從這裡開出來

自動喚醒

不過在用的人應該不少人有這樣的困擾,為什麼休眠中的電腦會突然自己喚醒,或是動到滑鼠就喚醒了(撞到桌子連動感應到滑鼠),印題出自於以下
  • 滑鼠喚醒
  • 網路喚醒
網卡一般預設應該是關掉的,但是如果你確定沒動到滑鼠還是自己開機或是筆電連上wifi就自己開機,八成是網卡惹的禍。
對著左下的win按右鍵,找到裝置管理員可以打開他,然後找到你的網卡打勾
只允許 magic 封裝喚醒電腦
不然你會因為一堆莫名其妙的原因導致網卡啟動電腦。

滑鼠

再來處理滑鼠,可以透過這個指令查看那些裝置具有喚醒權限
powercfg -DEVICEQUERY wake_armed
看不爽的都停掉也是個辦法,我自己是有留鍵盤方便開機。
值得注意的是,有些滑鼠會有兩個以上的裝置!比如說羅技有3個,有太陽的無線接收器可能是因為可以接收6個裝置,所以同時有了鍵盤與滑鼠2個,3個都要關掉,不然滑鼠動到還是會喚醒。
關掉的方法如下。
至於有幾個妳就把滑鼠拔掉看看少幾個就知道,然後可以從ID去看說到底是哪一個。
這樣就不會在莫名其妙自己喚醒了。

參考

2017年9月24日 星期日

Onedrive 已同步的綠色打勾消失不見

Onedrive 已同步的綠色打勾消失不見

我的電腦已經不見許久,不見的原因是因為系統還原過,最近新增了第二個Onedrive帳戶,沒想到新增完畢之後綠色就打勾就自己修復了!
從這裡新增第二個帳戶
新增完畢之後需要重新啟動電腦
可能會遇到的問題是系統變數 %onedrive% 會變成第二個帳戶,解決方法也很容易,自己到環境變數內修改即可。
更改回你要的位置
困擾了好久,意外解決了QuQ

2017年9月17日 星期日

Win10 1703 icon 圖示亂跑 插入圖示中間其他圖示跑掉

Win10 1703 icon 圖示亂跑 插入圖示中間其他圖示跑掉

如果直接全新安裝貌似不會有這個bug如果是升級上來會有這個問題,尤其是筆電

處理方法

有三個關鍵原因導致的
  • 升級1703非全新安裝
  • 貼齊格線
  • 文字放大

升級1703非全新安裝

只能重灌了,不能重灌就以下方法加減用~
如果是1604升級上來不會有事情,但是如果超過兩個版本也就是從1604之前一路升級上來的就會有這個狀況。

貼齊格線

右鍵→檢視→貼齊格線
直接不貼齊格線就正常了,不過可能要習慣一下。
或者也可以關掉之後重新打開也會恢復正常,但是重新開機之後又會不正常,又要重按一次。

文字放大

或者桌面→右鍵→顯示設定→縮放與版面配置改回100%也就正常了。
不過對於2K以上的螢幕或是筆電不得不放大,只能忍了或重灌。

2017年9月9日 星期六

Harris corner 角點偵測源代碼 source code

Harris corner 角點偵測源代碼 source code

bool harris(const vector<float>& p,
    size_t w, size_t y, size_t x)
{
    // 閥值
    constexpr float r = 10;
    constexpr float thre = ((r + 1)*(r + 1)) / r;
    // 二維讀取
    auto at2d = [&](int y, int x) {return p[y*w + x];};
    // 公式
    float Dxx = 2 * at2d(y, x) - at2d(y, x-1) - at2d(y, x+1);
    float Dyy = 2 * at2d(y, x) - at2d(y-1, x) - at2d(y+1, x);
    float Dxy = at2d(y+1, x+1) + at2d(y-1, x-1)
        - at2d(y-1, x+1) - at2d(y+1, x-1);
    Dxy /= 4;
    float Tr = Dxx + Dyy;
    float Det = Dxx * Dyy - Dxy*Dxy;
    // 判斷閥值
    if ((Tr*Tr / Det) < thre) {
        return 1;
    } return 0; 
}
沒有針對邊緣防呆,記得避開邊緣的點
測試圖