opencv實現(xiàn)圖像傾斜校正
本文實例為大家分享了opencv實現(xiàn)圖像傾斜校正的具體代碼,供大家參考,具體內(nèi)容如下
今天的任務(wù)是如圖這兩種情況,我現(xiàn)在的情況是和如圖一樣的,左圖左邊傾斜一點兒,那么我需要把左邊壓低傾斜校正。右圖,右邊傾斜我需要把右邊下壓到水平位置傾斜校正。我的場景不會有大角度的傾斜,就這么點可能的不會超過45°的小角度。
標(biāo)準(zhǔn)的傳統(tǒng)圖像處理方法。首先就是灰度,二值化,取輪廓,篩選得到目標(biāo)(面積最大的那個),得到傾斜角度,轉(zhuǎn)正。
具體過程就不詳細(xì)說了,都在代碼里面一看就懂。效果圖如下:
#include <iostream> #include"opencv2/opencv.hpp" using namespace std; using namespace cv; bool cmp_x(cv::Point pt1, cv::Point pt2) { ? ? return (pt1.x < pt2.x); } cv::Point2f get_mid_pt(cv::Point2f pt1, cv::Point2f pt2) { ? ? return cv::Point2f((pt1.x + pt2.x)/2.0,(pt1.y + pt2.y) / 2.0); } double get_point_angle(cv::Point2f pointO,cv::Point2f pointA) { ? ? double angle = 0; ? ? cv::Point2f point; ? ? double temp; ? ? point = cv::Point2f((pointA.x - pointO.x), (pointA.y - pointO.y)); ? ? if ((0==point.x) && (0==point.y)) ? ? { ? ? ? ? return 0; ? ? } ? ? if (0==point.x) ? ? { ? ? ? ? angle = 90; ? ? ? ? return angle; ? ? } ? ? if (0==point.y) ? ? { ? ? ? ? angle = 0; ? ? ? ? return angle; ? ? } ? ? temp = fabsf(float(point.y)/float(point.x)); ? ? temp = atan(temp); ? ? temp = temp*180/CV_PI ; ? ? if ((0<point.x)&&(0<point.y)) ? ? { ? ? ? ? angle = 360 - temp; ? ? ? ? return angle; ? ? } ? ? if ((0>point.x)&&(0<point.y)) ? ? { ? ? ? ? angle = 360 - (180 - temp); ? ? ? ? return angle; ? ? } ? ? if ((0<point.x)&&(0>point.y)) ? ? { ? ? ? ? angle = temp; ? ? ? ? return angle; ? ? } ? ? if ((0>point.x)&&(0>point.y)) ? ? { ? ? ? ? angle = 180 - temp; ? ? ? ? return angle; ? ? } ? ? printf("sceneDrawing :: getAngle error!"); ? ? return -1; } int RotateImage(const cv::Mat &src, double angle, cv::Mat &dst, cv::Mat &rot_matrix, bool crop = true, int flags = cv::INTER_NEAREST, ? ? ? ? ? ? ? ? int borderMode = cv::BORDER_CONSTANT, const cv::Scalar &borderValue = cv::Scalar()) { ? ? if(0 == src.cols * src.rows) { return 0;} ? ? cv::Point2f center(src.cols / 2.0f, src.rows / 2.0f); ? ? rot_matrix = cv::getRotationMatrix2D(center, angle, 1.0); ? ? if (crop) { ? ? ? ? if (dst.data == NULL) { ? ? ? ? ? ? dst = cv::Mat(src.rows, src.cols, src.type()); ? ? ? ? } ? ? } else { ? ? ? ? cv::Rect bbox = cv::RotatedRect(center, cv::Size2f(src.cols, src.rows), angle).boundingRect(); ? ? ? ? double *p = (double *) rot_matrix.data; ? ? ? ? p[2] += bbox.width / 2.0 - center.x; ? ? ? ? p[5] += bbox.height / 2.0 - center.y; ? ? ? ? if (dst.rows != bbox.height || dst.cols != bbox.width) { ? ? ? ? ? ? dst = cv::Mat(bbox.height, bbox.width, src.type()); ? ? ? ? } ? ? } ? ? cv::warpAffine(src, dst, rot_matrix, dst.size(), flags, borderMode, borderValue); ? ? return 0; } int main(int argc, char *argv[]) { ? ? cv::Mat img = cv::imread("/data_1/everyday/0325/13.jpeg"); ? ? cv::Mat m_gray,m_bi; ? ? cv::cvtColor(img,m_gray,CV_BGR2GRAY); ? ? cv::threshold(m_gray,m_bi,100,255,THRESH_BINARY_INV); ? ? vector<vector<Point>> contours; ? ? vector<Vec4i> hierarchy; ? ? findContours(m_bi,contours,hierarchy,RETR_TREE,CHAIN_APPROX_SIMPLE,Point()); ? ? RotatedRect rt_rot_max,rt_tmp; ? ? int max_szie = -1; ? ? for(int i=0;i<contours.size();i++) ? ? { ? ? ? ? rt_tmp = minAreaRect(Mat(contours[i])); ? ? ? ? if(rt_tmp.size.area() > max_szie) ? ? ? ? { ? ? ? ? ? ? max_szie = rt_tmp.size.area(); ? ? ? ? ? ? rt_rot_max = rt_tmp; ? ? ? ? } ? ? } ? ? std::vector<cv::Point2f> v_pt(4); ? ? rt_rot_max.points(v_pt.data()); ? ? std::sort(v_pt.begin(),v_pt.end(),cmp_x); ? ? cv::Point2f pt_left = get_mid_pt(v_pt[0], v_pt[1]); ? ? cv::Point2f pt_right = get_mid_pt(v_pt[2], v_pt[3]); ? ? double ang = get_point_angle(pt_left,pt_right); ? ? std::cout<<"ang="<<ang<<std::endl; ? ? cv::circle(img,v_pt[0],6,Scalar(50,12,189),3); ? ? cv::circle(img,v_pt[1],6,Scalar(10,255,255),3); ? ? cv::circle(img,v_pt[2],6,Scalar(150,120,19),3); ? ? cv::circle(img,v_pt[3],6,Scalar(0,0,0),3); ? ? cv::Mat m_rot,rot_matrix; ? ? RotateImage(img, -ang, m_rot, rot_matrix, false); ? ? cv::imshow("m_rot",m_rot); ? ? cv::imshow("m_bi",m_bi); ? ? cv::imshow("m_gray",m_gray); ? ? cv::imshow("img",img); ? ? cv::waitKey(0); ? ? return 0; }
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C語言中的自定義類型之結(jié)構(gòu)體與枚舉和聯(lián)合詳解
今天我們來學(xué)習(xí)一下自定義類型,自定義類型包括結(jié)構(gòu)體、枚舉、聯(lián)合體,小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考2022-06-06C++?分割字符串?dāng)?shù)據(jù)的實現(xiàn)方法
這篇文章主要介紹了C++?分割字符串?dāng)?shù)據(jù)的實現(xiàn)方法,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-09-09C語言進(jìn)階輸入輸出重定向與fopen函數(shù)使用示例詳解
這篇文章主要為大家介紹了C語言進(jìn)階輸入輸出重定向與fopen函數(shù)的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2022-02-02C++連接mysql數(shù)據(jù)庫并讀取數(shù)據(jù)的具體步驟
在實際開發(fā)中我們經(jīng)常需要對數(shù)據(jù)庫進(jìn)行訪問,針對不同類型的數(shù)據(jù)庫(如MySQL、sqLite、Access、Excel等),如果采用不同的方法進(jìn)行連接,會把我們搞崩潰,下面這篇文章主要給大家介紹了關(guān)于C++連接mysql數(shù)據(jù)庫并讀取數(shù)據(jù)的具體步驟,需要的朋友可以參考下2023-04-04