今天來說一下怎麼樣將這個旋轉的文字框矯正,大體思路:
二值化分割+邊緣檢測+最大外接矩形+透視變換 => 最終影象
ps: 本人用word畫的測試影象,另外是基於opencv3.3+vs2015
首先讀入,並且灰度轉換
g_src = imread("rotate.png");
if (g_src.empty())
//imshow("原始", g_src);
cvtcolor(g_src, g_img_gray,color_bgr2gray);
namedwindow(namewindow1, window_autosize);
建立乙個滑動條,進行二值化找到閾值
createtrackbar("閾值", namewindow1, &threshold_value, threshold_max, on_threshold);
能很明顯的看到矩形輪廓,接下來進行輪廓查詢
vectorhierarchy;
vector>contours;
for (int i = 0;i < contours.size();i++)
本來我們只需要根據邊緣尋找最小外接矩形,驗證尺寸是否是我們想要的,就可以了
但是遇到很乙個問題,也是我自己作死,用word畫圖,他會出現以下情況:
你以為只有乙個矩形框?那就錯了,其實它是類似這樣的:
兩個矩形框基本重疊在一起,我試著輸出了一下矩形四個頂點
會發現這兩個矩形四個頂點非常接近,所以我們需要修改演算法,剔除掉其中乙個,演算法思路:
把矩形四個頂點一一對應相減得到差值,算出距離,如果距離小於某個值,說明這四個頂點是非常接近的,
可以算出矩形周長,將周長小的剔除
vector>detector; //用來存放頂點
for (int i = 0;i < contours.size();i++)
point v1 = vertices[1] - vertices[0];
point v2 = vertices[2] - vertices[0];
double o = v1.x*v2.y - v2.x*v1.y;
if (o < 0.0) //逆時針儲存四個點
swap(vertices[1], vertices[3]);
cout << "vertices[0]" << vertices[0] << endl;
cout << "vertices[1]" << vertices[1] << endl;
cout << "vertices[2]" << vertices[2] << endl;
cout << "vertices[3]" << vertices[3] << endl;
vectorm;
for(int i=0;i<4;i++)
detector.push_back(m);
} }
vector< pair> toonearcandidates; //移除那些角點互相離的太近的四邊形 //移除角點太接近的元素
for (int i = 0;i < detector.size();i++) //選擇排序法
distsquared /= 4;
if (distsquared < 100) //
}} vectorremovalmask(detector.size(), false);
for (int i = 0;i < toonearcandidates.size();i++)
else
removalmask[removalindex] = true;
//cout << removalindex;
} markdetector.clear();
for (int i = 0;i < detector.size();i++) }
cout << markdetector.size() << endl;
vectorrotaterects;
for (int i = 0;i < markdetector.size();i++)
rotaterects.push_back(r);
}
這是求周長的函式:
float perimeter(const vector&a)//求多邊形周長。
然後得到最終結果:
可以看到我們已經將修正
接下來是貼出完整**:
#include#includeusing namespace std;
using namespace cv;
#define namewindow1 "二值化"
void on_threshold(int, void*);
int threshold_value = 180;
int threshold_max = 255;
mat g_src;
mat g_img_gray;
float perimeter(const vector&a)//求多邊形周長。
int main()
//imshow("原始", g_src);
cvtcolor(g_src, g_img_gray,color_bgr2gray);
namedwindow(namewindow1, window_autosize);
createtrackbar("閾值", namewindow1, &threshold_value, threshold_max, on_threshold);
on_threshold(0, 0);
waitkey(0);
return 0;
}void on_threshold(int, void*)
point v1 = vertices[1] - vertices[0];
point v2 = vertices[2] - vertices[0];
double o = v1.x*v2.y - v2.x*v1.y;
if (o < 0.0) //逆時針儲存四個點
swap(vertices[1], vertices[3]);
/*cout << "vertices[0]" << vertices[0] << endl;
cout << "vertices[1]" << vertices[1] << endl;
cout << "vertices[2]" << vertices[2] << endl;
cout << "vertices[3]" << vertices[3] << endl;*/
vectorm;
for(int i=0;i<4;i++)
detector.push_back(m);
} }/*cout << rotaterects.size()<> toonearcandidates;
for (int i = 0;i < detector.size();i++)
distsquared /= 4;
if (distsquared < 100)
}} vectorremovalmask(detector.size(), false);
for (int i = 0;i < toonearcandidates.size();i++)
else
removalmask[removalindex] = true;
//cout << removalindex;
} markdetector.clear();
for (int i = 0;i < detector.size();i++) }
cout << "檢測到的矩形個數為: "<< markdetector.size() << endl;
vectorrotaterects;
for (int i = 0;i < markdetector.size();i++)
rotaterects.push_back(r); }
for (size_t i = 0; i < rotaterects.size(); i++)
imshow(namewindow1, g_src);
}
文字框日曆
建立頭部 document.write 734 8 建立星期條目 document.write for i 0 i 7 i document.write week i document.write 建立日期條目 document.write for i 0 i 6 i document.write ...
文字框排版
文字框排版 我們之前學看文件的排版設定技巧,那麼還有乙個是文字框的排版設定,除了前面介紹到的段落排版以外,我們經常用到的還有文字框的排版,文字框排版在現實當中實踐應用包括了年會主持詞製作手卡的一些工作場景,那麼我們接下來就製作一下,首先在乙個空白文件中我們插入乙個文字框。插入文字框之後,清楚當中的預...
MFC 文字框 用法
mfc裡面的edit control控制項的用法是怎麼樣的,1.怎麼樣才能賦值給edit control控制項並在edit control控制項顯示出來 2.怎麼取得edit control控制項的值並傳遞給乙個變數?希望各位大俠幫幫忙!獲得edit cedit pboxone pboxone ce...