您好,登錄后才能下訂單哦!
本篇內容介紹了“C語言如何實現繪制繞線畫”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
簡單點來說,就是在木板上釘一圈釘子,通過繞線進行構圖,最終呈現出一幅圖像。
可以總結概括一下,
首先需要有一張圖,可以是彩色的,但是必須顏色比較分明。
對圖像進行灰度處理。
隨機生成 n 組數,就是每兩個釘子的組合。
計算 n 組數據連線所過圖像像素的平均數,求出最小的一組。
連接該組釘子,并對這條線經過的像素值分別加 m。
重復前面步驟 3 到步驟 5 直到繪制 z 條線結束循環。
#include<graphics.h> #include<math.h> #include<conio.h> #include<time.h> // 以下數據可以自己調節 #define PointNum 288 // 圓圈分的數量(一圈釘子的數量) #define LineNum 3000 // 循環繪制線的數量 #define RandNum 120 // 設置每次隨機生成連接的數量 #define AddColor 52 // 增加的值 0 到 255 值越小越線越集中,越大越分散 #define SIZE 800 // 圖像大小 // 以下參數不用調節 #define PI acos(-1.0) // 圓周率 #define R (SIZE / 2 - 10) // 半徑 struct PointS { int p; int x; int y; }; struct LineS { int StarP; // 起點 int EndP; // 終點 }; PointS points[PointNum]; LineS lines[RandNum]; // 為了判斷兩點是否連線定義的一維數組 bool LineXY[(1 + PointNum) * PointNum / 2] = { false }; bool Line_Rand[(1 + PointNum) * PointNum / 2] = { false }; // 兩條線是否連接 bool IsLineKed_Rand(int p1, int p2) { if (p1 >= p2) return Line_Rand[(1 + p1) * p1 / 2 + p2]; else return Line_Rand[(1 + p2) * p2 / 2 + p1]; } // 儲存已經繪制過的線 void Link_Rand(int p1, int p2) { if (p1 >= p2) Line_Rand[(1 + p1) * p1 / 2 + p2] = true; else Line_Rand[(1 + p2) * p2 / 2 + p1] = true; } // 將隨機生成的進行初始化 void Line2False() { for (int i = 0; i < (1 + PointNum) * PointNum / 2; i++) { Line_Rand[i] = false; } } // 判斷這兩個點是否連線 bool IsLinked(int p1, int p2) { if (p1 >= p2) return LineXY[(1 + p1) * p1 / 2 + p2]; else return LineXY[(1 + p2) * p2 / 2 + p1]; } // 儲存已經繪制過的線 void Link(int p1, int p2) { if (p1 >= p2) LineXY[(1 + p1) * p1 / 2 + p2] = true; else LineXY[(1 + p2) * p2 / 2 + p1] = true; } int Round(float x); // 取整 void InitPoints(); // 初始化點 void ColorToGray(IMAGE *pimg); // 彩色圖像轉換為灰度圖像 void Random(); // 產生隨機數 LineS Getline(IMAGE *pimg); // 獲取照片顏色 void ToColor(IMAGE *oriPic, IMAGE *linePic); // 給繞線圖賦予顏色 int main() { initgraph(SIZE, SIZE); setbkcolor(WHITE); cleardevice(); IMAGE imgpolt; // 加載原圖 IMAGE oriPic; // 儲存原圖 IMAGE linePic; // 線圖 loadimage(&imgpolt, _T("TG.jpeg"), SIZE, SIZE); // 加載原圖 oriPic = imgpolt; // 原圖 ColorToGray(&imgpolt); // 將圖片轉換為灰度 InitPoints(); // 初始化點 srand((unsigned)time(NULL)); // 生成隨機種子 for (int i = 0; i < LineNum; i++) { Random(); // 隨機生成 80 LineS myline = Getline(&imgpolt); // 計算 80 組點中平均值最小的 Link(myline.StarP, myline.EndP); // 記錄繪制過的線防止重復繪制 line(points[myline.StarP].x, points[myline.StarP].y, points[myline.EndP].x, points[myline.EndP].y); } _getch(); // /*該部分是給線條加上顏色*/ // saveimage(_T("test.png")); // 保存一下繞線圖 // loadimage(&linePic, _T("test.png"), SIZE, SIZE); // 重新加載繞線圖 // ToColor(&oriPic, &linePic); // 用原圖將繞線圖的顏色替換 // putimage(0, 0, &oriPic); // _getch(); return 0; } // 初始化點(想創新可以生成橢圓的位置坐標) void InitPoints() { for (int i = 0; i < PointNum; i++) { double a = i * PI * 2 / PointNum; points[i].p = i; points[i].x = int(SIZE / 2.0 + R * cos(a)); points[i].y = int(SIZE / 2.0 - R * sin(a)); setlinecolor(BLACK); circle(points[i].x, points[i].y, 3); } } // 彩色圖像轉換為灰度圖像 void ColorToGray(IMAGE *pimg) { DWORD *p = GetImageBuffer(pimg); // 獲取顯示緩沖區指針 COLORREF c; for (int i = pimg->getwidth() * pimg->getheight() - 1; i >= 0; i--) { c = BGR(p[i]); c = (GetRValue(c) * 299 + GetGValue(c) * 587 + GetBValue(c) * 114 + 500) / 1000; p[i] = RGB(c, c, c); } } // 隨機生成線 void Random() { for (int i = 0; i < RandNum; i++) { int starP; int endP; while (true) { starP = rand() % PointNum; endP = rand() % PointNum; if (IsLinked(starP, endP) == false && IsLineKed_Rand(starP, endP) == false) { break; } } lines[i].StarP = starP; lines[i].EndP = endP; Link_Rand(starP, endP); // 記錄隨機生成的線 } Line2False(); // 初始化線值 } // 四舍五入 int Round(float x) { return (int)(x < 0 ? x - 0.5 : x + 0.5); } // 獲取顏色最深的那一條線 LineS Getline(IMAGE *pimg) { LineS mylines; mylines.StarP = 0; mylines.EndP = 0; DWORD* p_data = GetImageBuffer(pimg); int width = pimg->getwidth(); double MaxNum = 255; int MYsteps; float X, Y; float CX, CY; for (int i = 0; i<RandNum; i++) { int SUMDN = 0; int x1 = points[lines[i].StarP].x; int y1 = points[lines[i].StarP].y; int x2 = points[lines[i].EndP].x; int y2 = points[lines[i].EndP].y; int steps = abs(x2 - x1) > abs(y2 - y1) ? abs(x2 - x1) : abs(y2 - y1); float x = (float)x1; float y = (float)y1; float cx = (float)(x2 - x1) / steps; float cy = (float)(y2 - y1) / steps; for (int j = 0; j < steps; j++) { int XIA = width * Round(y) + Round(x); SUMDN += GetRValue(p_data[XIA]); x += cx; y += cy; } double Aver = SUMDN / (steps * 1.0); if (Aver < MaxNum) { MaxNum = Aver; mylines = lines[i]; MYsteps = steps; X = (float)x1; Y = (float)y1; CX = cx; CY = cy; } } if (MaxNum == 255) { return mylines; } for (int j = 0; j < MYsteps; j++) { int XIA = width* Round(Y) + Round(X); int c = GetRValue(p_data[XIA]) + AddColor > 255 ? 255 : GetRValue(p_data[XIA]) + AddColor; p_data[XIA] = RGB(c, c, c); X += CX; Y += CY; } return mylines; } // 給線圖上色 void ToColor(IMAGE *oriPic, IMAGE *linePic) { DWORD* ori_data = GetImageBuffer(oriPic); DWORD* line_data = GetImageBuffer(linePic); for (int i = oriPic->getwidth() * oriPic->getheight() - 1; i >= 0; i--) { int oriR = GetRValue(ori_data[i]); int oriG = GetGValue(ori_data[i]); int oriB = GetBValue(ori_data[i]); int lineR = GetRValue(line_data[i]); int lineG = GetGValue(line_data[i]); int lineB = GetBValue(line_data[i]); int newPicR = (int)(255 - (255 - lineR)*(255 - oriR) / 255.0); int newPicG = (int)(255 - (255 - lineG)*(255 - oriG) / 255.0); int newPicB = (int)(255 - (255 - lineB)*(255 - oriB) / 255.0); ori_data[i] = RGB(newPicR, newPicG, newPicB); } }
“C語言如何實現繪制繞線畫”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。