圖片中點(diǎn)的旋轉(zhuǎn)

??在圖片處理中,經(jīng)常會(huì)遇到點(diǎn)的旋轉(zhuǎn)和坐標(biāo)系的旋轉(zhuǎn)問(wèn)題,這里對(duì)一個(gè)點(diǎn)(x, y)繞另一個(gè)點(diǎn)(x0, y0)旋轉(zhuǎn)的問(wèn)題做一個(gè)總結(jié)。
??一、在介紹之前,先總結(jié)一下編程的問(wèn)題,因?yàn)樵趯?shí)現(xiàn)的過(guò)程中碰到了一些坑:
??(1)c++中,三角函數(shù)的輸入和反三角函數(shù)的輸出都是:弧度。
??(2)opencv中涉及的都是角度,比如旋轉(zhuǎn)矩形的角度、仿射變換時(shí)旋轉(zhuǎn)圖片的角度。

??二、假設(shè)有兩個(gè)點(diǎn),一個(gè)點(diǎn)為p(x, y),另一個(gè)點(diǎn)為p0(x0, y0)。讓點(diǎn)p繞著點(diǎn)p0旋轉(zhuǎn)α(角度或者弧度都可以),求旋轉(zhuǎn)之后點(diǎn)的坐標(biāo)p1(x1, y1)。我們可以分成三個(gè)步驟來(lái)完成:(1)先將原點(diǎn)移動(dòng)到旋轉(zhuǎn)中心。(2)讓p0圍繞原點(diǎn)旋轉(zhuǎn)α。(3)移回坐標(biāo)原點(diǎn)。
??1、將原點(diǎn)移動(dòng)到旋轉(zhuǎn)中心p0處。那么點(diǎn)p0在新坐標(biāo)系中的坐標(biāo)為:(0, 0),點(diǎn)p1在新坐標(biāo)系中的坐標(biāo)為:(x - x0, y- y0)。
??2、將點(diǎn)(x - x0, y- y0)繞著原點(diǎn)旋轉(zhuǎn)角度α,將旋轉(zhuǎn)之后點(diǎn)的坐標(biāo)記為p2(x2, y2)。那么:
????x2 = (x - x0) * cosα + (y - y0) * sinα, ????y2 = -(x - x0) * sinα + (y - y0) * cosα
??3、將坐標(biāo)原點(diǎn)移回到原來(lái)的位置,那么可以根據(jù)點(diǎn)p2得到我們最終的結(jié)果p1(x1, y1)。即:
????x2 = (x - x0) * cosα + (y - y0) * sinα + x0, ??y2 = -(x - x0) * sinα + (y - y0) * cosα + y0

??三、應(yīng)用舉例
??圖片中有一條線段,線段L的兩個(gè)頂點(diǎn)分別為:p1(x1, y1),p2(x2, y3)。我們的目標(biāo)是將L旋轉(zhuǎn)為水平,旋轉(zhuǎn)之后的線段記為L'L'的兩個(gè)頂點(diǎn)分別為p3(x3, y3),p4(x4, y4),其中p3和p1對(duì)應(yīng),p4和p2對(duì)應(yīng),我們需要計(jì)算旋轉(zhuǎn)之后的點(diǎn)p3和p4的坐標(biāo)。
??實(shí)現(xiàn)代碼如下:

void point_rotate() {

    // 得到一張空白的灰度圖
    Mat image = Mat::zeros(Size(500, 500), CV_8UC1);
    float x0 = image.cols / 2;
    float y0 = image.rows / 2;

    // 初始化兩個(gè)點(diǎn), p1和p2
    Point p1 = Point(100, 100);
    Point p2 = Point(200, 120);

    //分別得到兩個(gè)點(diǎn)的坐標(biāo)
    float x1 = p1.x;
    float y1 = p1.y;
    float x2 = p2.x;
    float y2 = p2.y;

    //在圖上畫(huà)出兩個(gè)點(diǎn),以及兩個(gè)點(diǎn)連成的線L
    circle(image, p1, 3, Scalar(255), -1);
    circle(image, p2, 3, Scalar(255), -1);
    line(image, p1, p2, Scalar(255));

    // 計(jì)算L的偏轉(zhuǎn)角度
    float angle = atan((y2 - y1) / (x2 - x1));  //注意:這里得到的是弧度

    //以rotate_angle角度來(lái)旋轉(zhuǎn)圖片m,注意,opencv中的都是角度,所以這里需要把弧度轉(zhuǎn)化為角度
    // 旋轉(zhuǎn)的時(shí)候也需要注意,opencv中,負(fù)角度指的是順時(shí)針
    Mat rotate_img;
    float rotate_angle = angle * 180 / 3.14159265358979323846;
    Mat m = getRotationMatrix2D(Point2f(x0, y0), rotate_angle, 1);
    warpAffine(image, rotate_img, m, Size(image.cols, image.rows), 1, 0, 255);

    //計(jì)算p1在新圖片中對(duì)應(yīng)的坐標(biāo)p3
    float x3 = (x1 - x0) * cos(angle) + (y1 - y0) * sin(angle) + x0;
    float y3 = -(x1 - x0) * sin(angle) + (y1 - y0) * cos(angle) + y0;
    Point p3 = Point(int(x3), int(y3));

    //計(jì)算p2在新圖片中對(duì)應(yīng)的坐標(biāo)p4
    float x4 = (x2 - x0) * cos(angle) + (y2 - y0) * sin(angle) + x0;
    float y4 = -(x2 - x0) * sin(angle) + (y2 - y0) * cos(angle) + y0;
    Point p4 = Point(int(x4), int(y4));

    //在旋轉(zhuǎn)之后的圖片中畫(huà)出點(diǎn)p1, p2, p3, p4, 以及p1和p2的連線L,p3和p4的連線L'
    circle(rotate_img, p1, 3, Scalar(255), -1);
    circle(rotate_img, p2, 3, Scalar(255), -1);
    line(rotate_img, p1, p2, Scalar(255));

    circle(rotate_img, p3, 3, Scalar(255), -1);
    circle(rotate_img, p4, 3, Scalar(255), -1);
    line(rotate_img, p3, p4, Scalar(255));

    //標(biāo)識(shí)每個(gè)點(diǎn)的位置
    putText(rotate_img, "p1", p1, FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255));
    putText(rotate_img, "p2", p2, FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255));
    putText(rotate_img, "p3", p3, FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255));
    putText(rotate_img, "p4", p4, FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255));

    //畫(huà)出旋轉(zhuǎn)中心,以及p1,p3分別和旋轉(zhuǎn)中心的連線
    Point center = Point(x0, y0);
    circle(rotate_img, center, 3, Scalar(255), -1);
    line(rotate_img, p1, center, Scalar(255)); 
    line(rotate_img, p3, center, Scalar(255));

    //沿著p1點(diǎn)畫(huà)一條水平基準(zhǔn)線
    line(rotate_img, Point(0, 100), Point(rotate_img.cols, 100), Scalar(255));

    // 保存圖片image, rotate_img
    imwrite("E:\\image.bmp", image);
    imwrite("E:\\rotate_img.bmp", rotate_img);
}

??結(jié)果如下圖所示:



??在上圖的角度標(biāo)識(shí)中,角度1為:計(jì)算出的線段L的角度;角度2為:圖片旋轉(zhuǎn)的角度;角度3為:點(diǎn)p1旋轉(zhuǎn)的角度。從視覺(jué)效果上來(lái)看,這三個(gè)角度應(yīng)該是一致的。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容