bool Get_Character_ROI(License& License_ROI, vector<License>& Character_ROI) { Mat gray; cvtColor(License_ROI.mat, gray, COLOR_BGR2GRAY); Mat thresh; threshold(gray, thresh, 0, 255, THRESH_BINARY | THRESH_OTSU); Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3)); Mat close; morphologyEx(thresh, close, MORPH_CLOSE, kernel); vector<vector<Point>>contours; findContours(close, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE); for (int i = 0; i < contours.size(); i++) { double area = contourArea(contours[i]); //由于我们筛选出来的轮廓是无序的,故后续我们需要将字符重新排序 if (area > 200) { Rect rect = boundingRect(contours[i]); //计算外接矩形宽高比 double ratio = double(rect.height) / double(rect.width); if (ratio > 1) { Mat roi = License_ROI.mat(rect); resize(roi, roi, Size(50, 100), 1, 1, INTER_LINEAR); Character_ROI.push_back({ roi ,rect }); } } } //将筛选出来的字符轮廓 按照其左上角点坐标从左到右依次顺序排列 //冒泡排序 for (int i = 0; i < Character_ROI.size() - 1; i++) { for (int j = 0; j < Character_ROI.size() - 1 - i; j++) { if (Character_ROI[j].rect.x > Character_ROI[j + 1].rect.x) { License temp = Character_ROI[j]; Character_ROI[j] = Character_ROI[j + 1]; Character_ROI[j + 1] = temp; } } } if (Character_ROI.size() != 7) { return false; } return true; }
时间: 2024-04-26 15:20:58 浏览: 60
这段代码用于从车牌的ROI区域中分割出每个字符的ROI区域,并按照从左到右的顺序排列。具体流程如下:
1. 将车牌的ROI区域转换为灰度图像。
2. 对灰度图像进行二值化处理并进行闭运算,以便于分割字符。
3. 使用findContours()函数查找图像中的轮廓。
4. 对于每个轮廓,计算其面积和外接矩形宽高比。
5. 如果面积和宽高比符合要求,则将其截取出来作为字符的ROI区域。
6. 将所有的字符ROI区域按照从左到右的顺序进行排序,方便后续的识别处理。
7. 如果分割出的字符ROI区域不足7个,则返回false表示分割失败;否则返回true表示分割成功。
在上述流程中,使用了OpenCV中的函数cvtColor()、threshold()、getStructuringElement()、morphologyEx()、findContours()、boundingRect()、resize()等函数来进行图像转换、二值化、闭运算、轮廓查找、矩形区域计算、图像缩放等操作。通过这些操作,可以将车牌的字符分割出来,并按照从左到右的顺序进行排列,方便后续的字符识别处理。
相关问题
#include <iostream> #include <opencv2/imgcodecs.hpp> #include <opencv2/imgproc.hpp> #include <opencv2/videoio.hpp> #include <opencv2/highgui.hpp> #include <opencv2/video.hpp> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui_c.h> using namespace cv; using namespace std; int main(int argc, char** argv) { VideoCapture capture("D:/dvp/sample/dataset/traffic.mp4"); if (!capture.isOpened()) { //error in opening the video input cerr << "Unable to open file!" << endl; return 0; } Mat frame, roi, hsv_roi, mask; // take first frame of the video capture >> frame; // setup initial location of window Rect track_window(300, 200, 100, 50); // simply hardcoded the values // set up the ROI for tracking roi = frame(track_window); cvtColor(roi, hsv_roi, COLOR_BGR2HSV); inRange(hsv_roi, Scalar(0, 60, 32), Scalar(180, 255, 255), mask); float range_[] = { 0, 180 }; const float* range[] = { range_ }; Mat roi_hist; int histSize[] = { 180 }; int channels[] = { 0 }; calcHist(&hsv_roi, 1, channels, mask, roi_hist, 1, histSize, range); normalize(roi_hist, roi_hist, 0, 255, NORM_MINMAX); // Setup the termination criteria, either 10 iteration or move by atleast 1 pt TermCriteria term_crit(TermCriteria::EPS | TermCriteria::COUNT, 10, 1); while (true) { Mat hsv, dst; capture >> frame; if (frame.empty()) break; cvtColor(frame, hsv, COLOR_BGR2HSV); calcBackProject(&hsv, 1, channels, roi_hist, dst, range); // apply meanshift to get the new location meanShift(dst, track_window, term_crit); // Draw it on image rectangle(frame, track_window, 255, 2); imshow("img2", frame); setMouseCallback("img2", onMouse, 0); int keyboard = waitKey(30); if (keyboard == 'q' || keyboard == 27) break; } }帮我更改此段代码,使其能够通过gui使用鼠标来框选指定区域
以下是修改后的代码,可以通过GUI使用鼠标来框选指定区域:
```
#include <iostream>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/video.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui_c.h>
using namespace cv;
using namespace std;
Rect box; //定义一个矩形框,用于记录鼠标选择的区域
bool drawing_box = false; //标记是否正在通过鼠标绘制矩形框
void draw_box(Mat& img, Rect box)
{
//绘制矩形框
rectangle(img, box.tl(), box.br(), Scalar(0, 0, 255), 2);
}
void onMouse(int event, int x, int y, int flags, void* param)
{
Mat& image = *(Mat*)param;
switch (event)
{
case EVENT_MOUSEMOVE:
if (drawing_box)
{
//更新矩形框位置
box.width = x - box.x;
box.height = y - box.y;
}
break;
case EVENT_LBUTTONDOWN:
//开始绘制矩形框
drawing_box = true;
box = Rect(x, y, 0, 0);
break;
case EVENT_LBUTTONUP:
//结束绘制矩形框
drawing_box = false;
if (box.width < 0)
{
box.x += box.width;
box.width *= -1;
}
if (box.height < 0)
{
box.y += box.height;
box.height *= -1;
}
draw_box(image, box);
break;
}
}
int main(int argc, char** argv)
{
VideoCapture capture("D:/dvp/sample/dataset/traffic.mp4");
if (!capture.isOpened()) {
//error in opening the video input
cerr << "Unable to open file!" << endl;
return 0;
}
Mat frame, roi, hsv_roi, mask;
// take first frame of the video
capture >> frame;
namedWindow("img2");
setMouseCallback("img2", onMouse, &frame);
while (true) {
capture >> frame;
if (frame.empty()) break;
if (!box.empty()) {
// set up the ROI for tracking
roi = frame(box);
cvtColor(roi, hsv_roi, COLOR_BGR2HSV);
inRange(hsv_roi, Scalar(0, 60, 32), Scalar(180, 255, 255), mask);
float range_[] = { 0, 180 };
const float* range[] = { range_ };
Mat roi_hist;
int histSize[] = { 180 };
int channels[] = { 0 };
calcHist(&hsv_roi, 1, channels, mask, roi_hist, 1, histSize, range);
normalize(roi_hist, roi_hist, 0, 255, NORM_MINMAX);
// Setup the termination criteria, either 10 iteration or move by atleast 1 pt
TermCriteria term_crit(TermCriteria::EPS | TermCriteria::COUNT, 10, 1);
Mat hsv, dst;
cvtColor(frame, hsv, COLOR_BGR2HSV);
calcBackProject(&hsv, 1, channels, roi_hist, dst, range);
// apply meanshift to get the new location
meanShift(dst, box, term_crit);
// Draw it on image
rectangle(frame, box, 255, 2);
}
imshow("img2", frame);
int keyboard = waitKey(30);
if (keyboard == 'q' || keyboard == 27) break;
}
return 0;
}
```
在主函数中,我们添加了一个名为“img2”的窗口,并将其用作鼠标事件的回调函数。在主循环中,我们检查矩形框是否已经被绘制,如果是,则设置ROI并进行跟踪。最后,在每个循环迭代中,我们都显示图像,并等待用户按下“q”或“ESC”键退出程序。
阅读全文