山东轻工业学院2012届本科生毕业设计(论文)
图像的每一个像素的横向及纵向梯度近似值可用以下的公式结合,来计算梯度的大小:
G?Gx?Gy22 公式(4-5)
然后可用以下公式计算梯度方向。
?Gy??arctan??G?x???? 公式(4-6)
在以上例子中,如果以上的角度?等于零,即代表图像该处拥有纵向边缘,左方较右方暗。
2、代码实现
int[] marginalMx = { -1, 0, 1, -2, 0, 2, -1, 0, 1 }; //sobel模板 int[] marginalMy = { 1, 2, 1, 0, 0, 0, -1, -2, -1 }; int[,] dlta = new int[nHeight, nWidth];
for (int y = 0; y < nHeight; ++y) //sobel算子 {
for (int x = 0; x < nWidth; ++x) {
if (!(x <= 0 || x >= nWidth - 1 || y <= 0 || y >= nHeight - 1)) {
pp = p; Sx = 0; Sy = 0;
for (int i = -1; i <= 1; i++) for (int j = -1; j <= 1; j++) {
pp += (j * 3 + stride * i);
Sx += pp[0] * marginalMx[(i + 1) * 3 + j + 1]; Sy += pp[0] * marginalMy[(i + 1) * 3 + j + 1]; pp = p; }
m[y, x] = (int)(Math.Sqrt(Sx * Sx + Sy * Sy)); if (m[y, x] > valve / 2) //增强白点
19
山东轻工业学院2012届本科生毕业设计(论文)
{
if (p[0] > 240) {
m[y, x] += valve; }
else if (p[0] > 220) {
m[y, x] += (float)(valve * 0.8); }
else if (p[0] > 200) {
m[y, x] += (float)(valve * 0.6); }
else if (p[0] > 180) {
m[y, x] += (float)(valve * 0.4); }
else if (p[0] > 160) {
m[y, x] += (float)(valve * 0.2); } } float tan; if (Sx != 0) {
tan = Sy / Sx; }
else tan = 10000;
if (-0.41421356 <= tan && tan < 0.41421356)//角度为-22.5度到22.5度之间
{
dlta[y, x] = 0; }
else if (0.41421356 <= tan && tan < 2.41421356)//角度为22.5度到67.5度之间
20
山东轻工业学院2012届本科生毕业设计(论文)
{
dlta[y,x]=1; }
else if (tan >= 2.41421356 || tan < -2.41421356)//角度为67.5度到90度之间或-90度到-67.5度
{
dlta[y,x]= 2; 3、效果图
} else {
dlta[y, x] = 3;//m[y,x] = 0; } } else
m[y, x] = 0; p += 3; if (m[y, x] > 0) {
sumCount++; sumM += m[y, x]; } } }
图4-6 Sobel边缘检测后的图像
21
山东轻工业学院2012届本科生毕业设计(论文)
4、结果分析
Sobel算子根据像素点上下、左右邻点灰度加权差,在边缘处达到极值这一现象检测边缘。对噪声具有平滑作用,提供较为精确地边缘方向信息,边缘定位精度不够高,但对于车牌的粗略定位还是能起作用的,效果比较好,尤其是对高斯滤波过后的图片。
4.2.2 车牌定位分割 1、原理
采用纹理跳变进行扫描,行扫描法是利用了车牌的连续特性。车牌区域有连续7个字符,而且字符与字符之间的距离在一定范围内。定义从目标到背景或者从背景到目标为一个跳变。牌照区域相对于其它非车牌区域跳变多,而且间距在定范围内和跳变次数大于一定次数,并且连续满足上述要求的行要达到一定的数目。
按从下到上的顺序扫描,对图像的每一行进行从左向右的扫描,碰到跳变点记录下当前位置,如果某行连续20个跳变点以上,并且前一个跳变点和后一个跳变点的距离在30个像素内,就记录下起始点和终止点位置,如果连续有10行以上这样的跳变点,则认为该区域就是车牌预选区域。
本文先对图片从头扫描到底,对符合规律跳变的点存入数组countMatch,也记入行列数至数组mark;对数组countMatch进行去噪,除去不符合连续跳变的地方和上半部分面积;对数组countMatch进行2*6的粗定位;通过处理定位车牌四边,并在图上做出标记,分割出车牌区域并显示。
2、代码实现
if (m[y + i, pWH - 1] > 0 && m[y + i, pWH] <= 0)//白-->黑 {
pWHR = pWH - 1; if (pWL != pWHL) {
if ((Wmin <= (pWR - pWL) && (pWR - pWL) <= Wmax) || (Bmin <= (pWHL - pWR - 1) && (pWHL - pWR - 1) <= Bmax) || (Wmin <= (pWHR - pWHL) && (pWHR - pWHL) <= Wmax))
{
if (-pWL + pWHR < 30) //记录该点 {
double rate1 = Wmax / (Math.Abs((pWR - pWL) -
22
山东轻工业学院2012届本科生毕业设计(论文)
(Wmax - Wmin)) / 2 + 1);
double rate2 = Wmax / (Math.Abs((pWHR - pWHL) - (Wmax - Wmin)) / 2 + 1);
double rate3 = Bmax * 3 / (pWHL - pWR);
mark[y / div, pWL + (pWR - pWL) / 2] += (int)(rate3 + rate2 + rate2);
} }
if (pWR - pWL > 2 * lv) {
for (int t = pWL + lv / 2; t < pWR - lv / 2; t += lv) //连续白(或)宽于一个字符宽度
{
countMatch[y / div, t / lv] = -1; } }
if (pWHL - pWR - 1 > 2 * lv) {
for (int t = pWR + lv / 2; t < pWHL - lv / 2; t += lv) {
countMatch[y / div, t / lv] -= 1; } }
if (pWHR - pWHL > 2 * lv) {
for (int t = pWHL + lv / 2; t < pWHR - lv / 2; t += lv) {
countMatch[y / div, t / lv] -= 1; } } }
3、效果图
23