纯粹原创转载请注明本文章地址https://blog.csdn.net/smalbig/article/details/104561586 1.椭圆Roi的由来 使用opencv开发在计算机视觉有时需要获取一个椭圆形的Roi。比如一个倾斜的圆在不想或由于现场条件限制无法进行透视矫正时需要使用椭圆形的Roi对区域内进行各种操作如二值化边缘检测轮廓分析等等。以此来提高检测速度和精度。
Roi在我看来就是一个有一定几何形状的点集合即vector Roi。对图像的操作归根结底就是对像素的操作图像上像素的位置使用二维点表示的所以只要获取了感兴趣的二维点就能对图像进行相应的操作。所以椭圆Roi就是获得一个椭圆内所有点的坐标即可。 2.椭圆方程 P是椭圆上任意一点Px , y F1和F2是椭圆的两个焦点 c是椭圆的焦距即焦点到中心的距离 a是椭圆长轴的大小即中心到椭圆最远的点 b是椭圆短轴的大小即中心点到椭圆最近的点 |PF1| 和 |PF2| 是 Px , y到F1和F2的距离 椭圆满足|PF1| |PF2| 2a; b² c² a²换言之只要一个点Px,y满足以上式子它就是椭圆里的点把所有这样的点存到容器里就得到一个椭圆Roi。
3.伪代码如图下载后向右旋转90°即可 3.C实现代码如下
#include "stdafx.h"#include #include #include using namespace cv;using namespace std;vectorGetEllipoints(int a, int b, Point2i center) {a 300; b 200; center Point2i(400, 300);vector Ellipoints;int c sqrt(pow((a), 2) - pow((b), 2));Point2i F1 Point2i(center.x - c,center.y);Point2i F2 Point2i(center.x c, center.y);for (int i center.x - a; i < center.x a; i) {for (int j center.y - b; j < center.y b; j) {int PF1 sqrt(pow((i - F1.x), 2) pow((j - F1.y), 2));int PF2 sqrt(pow((i - F2.x), 2) pow((j - F2.y), 2));if (((PF1 PF2) < 2 * a)| ((PF1 PF2) < 2 * a)) {Ellipoints.push_back(Point2i(i, j));}}}return Ellipoints;}int main(){vector ellipoints GetEllipoints(400, 200, Point2i(400,200));Mat M(600, 800, CV_8UC1);for (int i 0; i < ellipoints.size(); i) {circle(M, ellipoints.at(i), 1, Scalar(255));}imshow("elli", M);waitKey(0);return 0;}
4.opencv C例子如下 4.1本例做了一个椭圆区域内的图像取反操作
#include "stdafx.h"#include #include #include using namespace cv;using namespace std;vectorGetEllipoints(int a, int b, Point2i center) {//a 300; b 200; center Point2i(400, 300);vector Ellipoints;int c sqrt(pow((a), 2) - pow((b), 2));Point2i F1 Point2i(center.x - c,center.y);Point2i F2 Point2i(center.x c, center.y);for (int i center.x - a; i < center.x a; i) {for (int j center.y - b; j < center.y b; j) {int PF1 sqrt(pow((i - F1.x), 2) pow((j - F1.y), 2));int PF2 sqrt(pow((i - F2.x), 2) pow((j - F2.y), 2));if (((PF1 PF2) < 2 * a)| ((PF1 PF2) < 2 * a)) {Ellipoints.push_back(Point2i(i, j));}}}return Ellipoints;}int main(){vector ellipoints GetEllipoints(400, 200, Point2i(700,400));Mat M(600, 800, CV_8UC1);Mat explode imread("C:\\Users\\cdf5f6ce\\Desktop\\explode.png");int x, y;for (int i 0; i < ellipoints.size(); i) {x ellipoints.at(i).x; y ellipoints.at(i).y;explode.at(y, x)[0] 255 - explode.at(y, x)[0];explode.at(y, x)[1] 255 - explode.at(y, x)[1];explode.at(y, x)[2] 255 - explode.at(y, x)[2];}imshow("explode", explode);waitKey(0);return 0;}
效果如图 处理前 处理后 4.2本例在椭圆Roi内进行Canny边缘检测
#include "stdafx.h"#include #include #include using namespace cv;using namespace std;vectorGetEllipoints(int a, int b, Point2i center, vector int c sqrt(pow((a), 2) - pow((b), 2));Point2i F1 Point2i(center.x - c,center.y);Point2i F2 Point2i(center.x c, center.y);for (int i center.x - a; i < center.x a; i) {for (int j center.y - b; j < center.y b; j) {int PF1 sqrt(pow((i - F1.x), 2) pow((j - F1.y), 2));int PF2 sqrt(pow((i - F2.x), 2) pow((j - F2.y), 2));if (((PF1 PF2) < 2 * a-2)) {Ellipoints.push_back(Point2i(i, j));}if (((PF1 PF2) 2 * a ) | ((PF1 PF2) 2 * a-1)| ((PF1 PF2) 2 * a1)|((PF1 PF2) 2 * a2) | ((PF1 PF2) 2 * a3)| ((PF1 PF2) 2 * a-2)| ((PF1 PF2) 2 * a-3)| ((PF1 PF2) 2 * a-4)| ((PF1 PF2) 2 * a-5)| ((PF1 PF2) 2 * a4)| ((PF1 PF2) 2 * a5)| ((PF1 PF2) 2 * a-6)| ((PF1 PF2) 2 * a-7)| ((PF1 PF2) 2 * a6)| ((PF1 PF2) 2 * a7)) {edgePoints.push_back(Point2i(i, j));}}}return Ellipoints;}int main(){vector edgePoints;vector ellipoints GetEllipoints(400, 200, Point2i(700,400), edgePoints);Mat M(600, 800, CV_8UC1);Mat explode imread("C:\\Users\\cdf5f6ce\\Desktop\\explode.png");int x, y;vectorCannyRoi;Mat baseimg Mat(explode.size(), CV_8UC1);for (int i 0; i < ellipoints.size(); i) {x ellipoints.at(i).x; y ellipoints.at(i).y;int B explode.at(y, x)[0];int G explode.at(y, x)[1];int R explode.at(y, x)[2];//explode.at(y, x)[0] 255 - explode.at(y, x)[0];if (B 100 255;//explode.at(y, x)[1] 255 - explode.at(y, x)[1];//explode.at(y, x)[2] 255 - explode.at(y, x)[2];explode.at(y, x)[1] 255;explode.at(y, x)[2] 255;baseimg.at(y, x) 255;}else {explode.at(y, x)[0] 0;baseimg.at(y, x) 0;//explode.at(y, x)[1] 255 - explode.at(y, x)[1];//explode.at(y, x)[2] 255 - explode.at(y, x)[2];explode.at(y, x)[1] 0;explode.at(y, x)[2] 0;}}Canny(baseimg, explode, 80, 255);threshold(explode, explode, 80, 255, THRESH_BINARY);//try {for (int i 0; i < edgePoints.size(); i) {explode.at(edgePoints.at(i).y, edgePoints.at(i).x) 0;//explode.at(edgePoints.at(i).y, edgePoints.at(i).x)[0];//explode.at(edgePoints.at(i).y, edgePoints.at(i).x)[1] 0;//explode.at(edgePoints.at(i).y, edgePoints.at(i).x)[2] 0;}//}//catch(cv::Exception){////}//threshold(CannyRoi, CannyRoi, 26, 255,THRESH_BINARY);//imshow("baseimg", baseimg);imshow("explode", explode);waitKey(0);return 0;
处理前 处理后 完