日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > c/c++ >内容正文

c/c++

OpenCV C++实现树结构可视化(画出一棵四叉树)

發(fā)布時(shí)間:2024/3/13 c/c++ 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 OpenCV C++实现树结构可视化(画出一棵四叉树) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

這是之前那篇關(guān)于C++實(shí)現(xiàn)決策樹(shù)的子問(wèn)題。用不了Python的Matplotlib,只能用OpenCV手撕。
假定我們要實(shí)現(xiàn)這樣一個(gè)三層四叉樹(shù)的結(jié)構(gòu)。(畫(huà)圖軟件太費(fèi)時(shí)間了直接紙上畫(huà)了)需要的是畫(huà)圓,直線和中間標(biāo)的index寫(xiě)字。最主要的是求圓心坐標(biāo)。

背景圖片我是拿windows自帶的畫(huà)圖弄了個(gè)20000*20000的全空白jpg。
一、建立樹(shù)結(jié)構(gòu)

遍歷了一下,結(jié)果是這樣沒(méi)錯(cuò)。
二、計(jì)算坐標(biāo)
然后拿CV畫(huà)圖比較麻煩的一點(diǎn)就是坐標(biāo)的計(jì)算。
假定:最底層的是所有4的i次方個(gè)葉子節(jié)點(diǎn)的圓相切。每4個(gè)葉子節(jié)點(diǎn)圓上一層的根節(jié)點(diǎn)圓橫坐標(biāo)在第2、3個(gè)葉子節(jié)點(diǎn)的正中間位置。
如圖,這是一個(gè)三層的滿四叉樹(shù),以此為例。層數(shù)i取值為0-2。求出最大層數(shù)為max(此處為2)。設(shè)d為每個(gè)小圓的直徑,r為半徑,△H為每一層的高度。(d=2r)
1.每層開(kāi)始A->G->……->T->C坐標(biāo)總長(zhǎng)度Li的計(jì)算
可以看出,除了第0層是單個(gè)根節(jié)點(diǎn),最底層是所有4max 個(gè)圓相切,這兩層是特殊的,要單獨(dú)討論。其他中間層都是遵循規(guī)律的。
最底層長(zhǎng)度L2=16 d=42 d。
第二層,所有圓的長(zhǎng)度要減去最左和最右兩個(gè)圓的直徑,即L1=4maxd-4d。
該規(guī)律可通過(guò)四層滿四叉樹(shù)來(lái)泛化:
L1=4max d-16d
L2=4maxd-4d
L3=4max d

最后得到:
所以除了第一層和最底層,中間層的長(zhǎng)度Li=4max-4max-id。
最底層長(zhǎng)度L底=4max d。
2.每層的各個(gè)A->G->T->C坐標(biāo)單長(zhǎng)度L0的計(jì)算
1,第0層和最底層是特殊的,單獨(dú)討論。
將Li的長(zhǎng)度細(xì)分為若干等長(zhǎng)L0,一個(gè)根節(jié)點(diǎn)對(duì)應(yīng)一個(gè)L0。
第1層總長(zhǎng)度為L(zhǎng)1,則L0=L1。
第2層總長(zhǎng)度為L(zhǎng)2,則L0=L2/4-d。因?yàn)橐蟮氖茿->G->T->C的長(zhǎng)度,最底層一開(kāi)始是統(tǒng)一計(jì)算一堆圓的直徑,所以多了最左和最右2個(gè)半徑。
為了泛化中間層規(guī)律,再次采用四層滿四叉樹(shù):
L01=L1
L02=3L2/15
L03=L3/16-d
五層滿四叉樹(shù):
L03=3L3/63
L04=L4/64-d

最后得到:
所以除了第一層和最底層,中間層的長(zhǎng)度L0i=3Li/(4i -1)。
最底層長(zhǎng)度L0底=L底/(4max-1)-d。
3.得到A,G,T,C的坐標(biāo)
假設(shè)某個(gè)根節(jié)點(diǎn)的坐標(biāo)為(x0,y0)。那么:
A(x0-L0/2,y0+△H)
G(x0-L0/6,y0+△H)
T(x0+L0/6,y0+△H)
C(x0+L0/2,y0+△H)
4.算法實(shí)現(xiàn)
此處樹(shù)的結(jié)構(gòu)體里我加了個(gè)tag,來(lái)區(qū)分節(jié)點(diǎn)的類(lèi)型。以A點(diǎn)為例:

if (t->tag == 'a'){double L = pow(4, maxLayer) * 2 * radius - pow(4, maxLayer - t->layer) * 2 * radius;double L0 = L * 3 / (pow(4, t->layer) - 1);if (t->aleaf == NULL && t->gleaf == NULL && t->tleaf == NULL && t->cleaf == NULL){L = pow(4, maxLayer) * 2 * radius;L0 = L / pow(4, t->layer - 1) - 2 * radius;}pointX += -L0 / 2;pointY += 1000;}

三、做出圖形
1.三層滿四叉樹(shù)

2.四層滿四叉樹(shù)

3.實(shí)現(xiàn)目標(biāo)樹(shù)結(jié)構(gòu)
字體和圓形大小比1、2中有放大。

結(jié)論:我在反思是不是應(yīng)該好好學(xué)一下Python,總這么手撕感覺(jué)不是個(gè)好辦法。
Over.
代碼

#include <iostream> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/highgui/highgui_c.h> #include <opencv2/opencv.hpp> #include <opencv2/imgproc.hpp> using namespace std; using namespace cv; struct treeNode {int layer;int index;char tag;treeNode* aleaf;treeNode* gleaf;treeNode* tleaf;treeNode* cleaf;treeNode() :index(0), layer(0), tag(' '), aleaf(NULL), gleaf(NULL), tleaf(NULL), cleaf(NULL) {} }; treeNode* createtreeNode() {treeNode* t = new treeNode();t->aleaf = new treeNode();t->gleaf = new treeNode();t->tleaf = new treeNode();t->cleaf = new treeNode();t->aleaf->layer = 1;t->gleaf->layer = 1;t->tleaf->layer = 1;t->cleaf->layer = 1;t->aleaf->index = 1;t->gleaf->index = 2;t->tleaf->index = 3;t->cleaf->index = 4;t->aleaf->tag = 'a';t->gleaf->tag = 'g';t->tleaf->tag = 't';t->cleaf->tag = 'c';t->aleaf->aleaf = new treeNode();t->aleaf->tleaf = new treeNode();t->cleaf->aleaf = new treeNode();t->cleaf->gleaf = new treeNode();t->cleaf->cleaf = new treeNode();t->aleaf->aleaf->layer = 2;t->aleaf->tleaf->layer = 2;t->cleaf->aleaf->layer = 2;t->cleaf->gleaf->layer = 2;t->cleaf->cleaf->layer = 2;t->aleaf->aleaf->index = 5;t->aleaf->tleaf->index = 6;t->cleaf->aleaf->index = 7;t->cleaf->gleaf->index = 8;t->cleaf->cleaf->index = 9;t->aleaf->aleaf->tag = 'a';t->aleaf->tleaf->tag = 't';t->cleaf->aleaf->tag = 'a';t->cleaf->gleaf->tag = 'g';t->cleaf->cleaf->tag = 'c';return t; } vector<int> countLayer; void traverseTree(treeNode* t) {if (t == NULL) return;else{countLayer.push_back(t->layer);cout << "index:" << t->index << endl;traverseTree(t->aleaf);traverseTree(t->gleaf);traverseTree(t->tleaf);traverseTree(t->cleaf);} } int findMaxLayer(vector<int> c) {int size = c.size();int max = 0;for (int i = 0; i < size; i++){if (c[i] > max)max = c[i];}return max; } Mat image = imread("untitled.jpg"); string intToChar(int n) {char* num = new char[10];_itoa_s(n, num, sizeof(num), 10);string s = num;delete[] num;return s; } void drawTree(treeNode* t, double pointX, double pointY, string output) {int radius = 200;//r;int maxLayer = findMaxLayer(countLayer);double previousX = pointX;double previousY = pointY;if (t == NULL) return;else{if (t->tag == 'a'){double L = pow(4, maxLayer) * 2 * radius - pow(4, maxLayer - t->layer) * 2 * radius;double L0 = L * 3 / (pow(4, t->layer) - 1);if (t->aleaf == NULL && t->gleaf == NULL && t->tleaf == NULL && t->cleaf == NULL){L = pow(4, maxLayer) * 2 * radius;L0 = L / pow(4, t->layer - 1) - 2 * radius;}pointX += -L0 / 2;pointY += 1000;}else if (t->tag == 'g'){double L = pow(4, maxLayer) * 2 * radius - pow(4, maxLayer - t->layer) * 2 * radius;double L0 = L * 3 / (pow(4, t->layer) - 1);if (t->aleaf == NULL && t->gleaf == NULL && t->tleaf == NULL && t->cleaf == NULL){L = pow(4, maxLayer) * 2 * radius;L0 = L / pow(4, t->layer - 1) - 2 * radius;}pointX += -L0 / 6;pointY += 1000;}else if (t->tag == 't'){double L = pow(4, maxLayer) * 2 * radius - pow(4, maxLayer - t->layer) * 2 * radius;double L0 = L * 3 / (pow(4, t->layer) - 1);if (t->aleaf == NULL && t->gleaf == NULL && t->tleaf == NULL && t->cleaf == NULL){L = pow(4, maxLayer) * 2 * radius;L0 = L / pow(4, t->layer - 1) - 2 * radius;}pointX += L0 / 6;pointY += 1000;}else if (t->tag == 'c'){double L = pow(4, maxLayer) * 2 * radius - pow(4, maxLayer - t->layer) * 2 * radius;double L0 = L * 3 / (pow(4, t->layer) - 1);if (t->aleaf == NULL && t->gleaf == NULL && t->tleaf == NULL && t->cleaf == NULL){L = pow(4, maxLayer) * 2 * radius;L0 = L / pow(4, t->layer - 1) - 2 * radius;}pointX += L0 / 2;pointY += 1000;}else if (t->tag == ' '){pointX = 10000;pointY = 1000;}output = intToChar(t->index);line(image, Point(previousX, previousY), Point(pointX, pointY), Scalar(0, 0, 0), 20);circle(image, Point(previousX, previousY), radius, Scalar(0, 0, 0), 20);circle(image, Point(previousX, previousY), radius - 10, Scalar(255, 255, 255), -1);circle(image, Point(pointX, pointY), radius, Scalar(0, 0, 0), 20);circle(image, Point(pointX, pointY), radius - 10, Scalar(255, 255, 255), -1);drawTree(t->aleaf, pointX, pointY, output);drawTree(t->gleaf, pointX, pointY, output);drawTree(t->tleaf, pointX, pointY, output);drawTree(t->cleaf, pointX, pointY, output);putText(image, &output[0], Point(pointX - 100, pointY + 100), 0, 10, Scalar(0, 0, 0), 20);} } void drawTreeTotal(treeNode* t) {double xCircle = 10000;//x0;double yCircle = 1000;//y0;namedWindow("tree", CV_WINDOW_NORMAL);imshow("tree", image);drawTree(t, xCircle, yCircle,""); } int main() {treeNode* t = createtreeNode();traverseTree(t);drawTree(t, 10000, 1000, "");drawTreeTotal(t);waitKey(0);system("pause");return 0; }

總結(jié)

以上是生活随笔為你收集整理的OpenCV C++实现树结构可视化(画出一棵四叉树)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。