*------------------------------ - 程序介绍------------------------------*/
//版本:VS2017 + Opencv2.4.9
//描述:OpenCV学习之路——车牌识别之车牌定位
/*-----------------------------------------------------------------------*/
#include "opencv.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2\core\core.hpp"
#include "vector"
#include "iostream"
#include "time.h"
using namespace cv;
using namespace std;
Mat histeq(Mat in)
{
Mat out(in.size(), in.type());
if (in.channels() == 3) {
Mat hsv;
vector<Mat> hsvSplit;
cvtColor(in, hsv, CV_BGR2HSV);
split(hsv, hsvSplit);
equalizeHist(hsvSplit[2], hsvSplit[2]);
merge(hsvSplit, hsv);
cvtColor(hsv, out, CV_HSV2BGR);
}
else if (in.channels() == 1) {
equalizeHist(in, out);
}
return out;
}
//! 对minAreaRect获得的最小外接矩形,用纵横比进行判断
bool verifySizes(RotatedRect mr)
{
float error = 0.3;
//Spain car plate size: 52x11 aspect 4,7272
//China car plate size: 440mm*140mm,aspect 3.142857
float aspect = 3.142857;
//Set a min and max area. All other patchs are discarded
int min= 1*aspect*1; // minimum area
int max= 2000*aspect*2000; // maximum area
//int min = 44 * 14 * m_verifyMin; // minimum area
//int max = 44 * 14 * m_verifyMax; // maximum area
//Get only patchs that match to a respect ratio.
float rmin = aspect - aspect*error;
float rmax = aspect + aspect*error;
int area = mr.size.height * mr.size.width;
float r = (float)mr.size.width / (float)mr.size.height;
if (r < 1)
{
r = (float)mr.size.height / (float)mr.size.width;
}
if ((area < min || area > max) || (r < rmin || r > rmax))
{
return false;
}
else
{
return true;
}
}
Mat Gaussian(Mat &img) {
Mat out;
GaussianBlur(img, out, Size(3, 3),
0, 0, BORDER_DEFAULT);
return out;
}
Mat Grayscale(Mat &img) {
Mat out;
cvtColor(img, out, CV_RGB2GRAY);
return out;
}
Mat Sobel(Mat &img) {
Mat out;
Mat grad_x, grad_y;
Mat abs_grad_x, abs_grad_y;
//X方向
//Sobel(img, grad_x, CV_16S, 1, 0, 3, 1, 1, BORDER_DEFAULT);
//convertScaleAbs(grad_x, abs_grad_x);
Sobel(img, img, CV_16S, 1, 0, 3, 1, 1, BORDER_DEFAULT);
convertScaleAbs(img, out);
//Y方向
//Sobel(img, grad_y, CV_16S, 0, 1, 3, 1, 1, BORDER_DEFAULT);
//convertScaleAbs(grad_y, abs_grad_y);
//convertScaleAbs(img, out);
//合并
//addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, out);
return out;
}
Mat TwoValued(Mat &img) {
Mat out;
threshold(img, out, 0, 255, CV_THRESH_OTSU + CV_THRESH_BINARY);
//threshold(img, out, 100, 255, CV_THRESH_BINARY);
return out;
}
Mat Close(Mat &img) {
Mat out;
//Mat element(5, 5, CV_8U, cv::Scalar(1));
Mat element = getStructuringElement(MORPH_RECT, Size(17, 5));
morphologyEx(img, out, cv::MORPH_CLOSE, element);
return out;
}
void Contour(Mat &img, Mat &out) {
RNG rng(12345);
vector< Mat > contours(1000);
vector<Vec4i> hierarchy(1000);
findContours(img, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
vector< Mat >::iterator itc = contours.begin();
vector<RotatedRect> rects;
int t = 0;
while (itc != contours.end()) {
//Create bounding rect of object
RotatedRect mr = minAreaRect(Mat(*itc));
//large the rect for more
if (!verifySizes(mr)) {
itc = contours.erase(itc);
}
else {
++itc;
rects.push_back(mr);
}
}
cv::Mat result;
img.copyTo(result);
for (int i = 0; i< contours.size(); i++)
{
drawContours(result, contours, i, Scalar(0, 0, 255), 2, 8, vector<Vec4i>(), 0, Point());
//drawContours(result, contours, i, Scalar(255), 2);
}
//imshow("画轮廓", out);
for (int i = 0; i < rects.size(); i++) {
circle(result, rects[i].center, 3, Scalar(0, 255, 0), -1);
float minSize = (rects[i].size.width < rects[i].size.height) ? rects[i].size.width : rects[i].size.height;
//minSize = minSize - minSize*0.5;
srand(time(NULL));
Mat mask;
mask.create(out.rows + 2, out.cols + 2, CV_8UC1);
mask = Scalar::all(0);
int loDiff = 30;
int upDiff = 30;
int connectivity = 4;
int newMaskVal = 255;
int NumSeeds = 10;
Rect ccomp;
int flags = connectivity + (newMaskVal << 8) + CV_FLOODFILL_FIXED_RANGE + CV_FLOODFILL_MASK_ONLY;
for (int j = 0; j < NumSeeds; j++) {
Point seed;
seed.x = rects[i].center.x + rand() % (int)minSize - (minSize / 2);
seed.y = rects[i].center.y + rand() % (int)minSize - (minSize / 2);
circle(result, seed, 1, Scalar(0, 255, 255), -1);
int area = floodFill(out, mask, seed, Scalar(255, 0, 0), &ccomp, Scalar(loDiff, loDiff, loDiff), Scalar(upDiff, upDiff, upDiff), flags);
}
imshow("漫水填充", mask);
vector<Point> pointsInterest;
Mat_<uchar>::iterator itMask = mask.begin<uchar>();
Mat_<uchar>::iterator end = mask.end<uchar>();
for (; itMask != end; ++itMask)
if (*itMask == 255)
pointsInterest.push_back(itMask.pos());
RotatedRect minRect = minAreaRect(pointsInterest);
if (verifySizes(minRect)) {
// rotated rectangle drawing
Point2f rect_points[4]; minRect.points(rect_points);
for (int j = 0; j < 4; j++)
line(result, rect_points[j], rect_points[(j + 1) % 4], Scalar(0, 0, 255), 1, 8);
//Get rotation matrix
float r = (float)minRect.size.width / (float)minRect.size.height;
float angle = minRect.angle;
if (r < 1)
angle = 90 + angle;
Mat rotmat = getRotationMatrix2D(minRect.center, angle, 1);
//Create and rotate image
Mat img_rotated;
warpAffine(out, img_rotated, rotmat, out.size(), CV_INTER_CUBIC);//实现旋转
//Crop image
Size rect_size = minRect.size;
if (r < 1)
swap(rect_size.width, rect_size.height);
Mat img_crop;
getRectSubPix(img_rotated, rect_size, minRect.center, img_crop);
Mat resultResized;
resultResized.create(33, 144, CV_8UC3);
resize(img_crop, resultResized, resultResized.size(), 0, 0, INTER_CUBIC);;
Equalize croped image
Mat grayResult;
cvtColor(resultResized, grayResult, CV_BGR2GRAY);// CV_RGB2GRAY
blur(grayResult, grayResult, Size(3, 3));
grayResult = histeq(grayResult);
if (1) {
stringstream ss(stringstream::in | stringstream::out);
ss << "haha" << "_" << i << ".jpg";
imwrite(ss.str(), grayResult);
}
}
}
}
int main() {
Mat img;
Mat out;
//Mat result;
//载入图片
img = imread("test1.jpg");//, CV_LOAD_IMAGE_GRAYSCALE);
img.copyTo(out);
//imshow ("原始图", img);
img = Gaussian(img);
imshow ("高斯模糊", img);
img = Grayscale(img);
imshow("灰度化", img);
img = Sobel(img);
imshow("Sobel_X", img);
img = TwoValued(img);
imshow("二值化", img);
img = Close(img);
imshow("闭操作", img);
Contour(img, out);
waitKey(0);
cvDestroyAllWindows();
}
car identify Location
最新推荐文章于 2022-02-25 10:10:30 发布