بایگانی برچسب برای: لبه یابی

الگوریتم Canny در ++C

لبه یاب کنی توسط جان اف کنی در سال 1986 ایجاد شد و هنوز یک لبه یاب استاندارد و با دقت و کیفیت بالا میباشد.الگوریتم لبه یابی کنی یکی از بهترین لبه یابها تا به امروز است. در ادامه روش کار این الگوریتم و هم چنین کد الگوریتم Canny در ++C را بررسی خواهیم کرد. این الگوریتم لبه یابی از سه بخش اصلی زیر تشکیل شده است:

  • تضعیف نویز
  • پیدا کردن نقاطی که بتوان آنها را به عنوان لبه در نظر گرفت
  • حذب نقاطی که احتمال لبه بودن آنها کم است

 

معیارهایی که در لبه یاب کنی مطرح است:
1 -پایین آوردن نرخ خطا- یعنی تا حد امکان هیچ لبه ای در تصویر نباید گم شود و هم چنین هیچ چیزی که لبه نیست نباید به جای لبه فرض شود. لبه هان پیدا شده تا حد ممکن به لبه ها اصلی
نزدیک باشند.

2 -لبه در مکان واقعی خود باشد- یعنی تا حد ممکن لبه ها کمترین فاصله را با مکان واقعی خود داشته باشند.
3 -بران هر لبه فقط یک پاسخ داشته باشیم.

4 -لبه ها کمترین ضخامت را داشته باشند- (در صورت امکان یک پیکسل).
لبه یاب کنی بخاطر توانایی در تولید لبه های نازک تا حد یک ییکسل برای لبه های پیوسته معروف شده است. این لبه یاب شامل چهار مرحله و چهار ورودی زیر است:
یک تصویر ورودی
یک پارامتر به نام سیگما جهت مقدار نرم کنندگی تصویر
یک حد آستانه بالا (Th)
یک حد آستانه پایین (Tl)

 

مراحل الگوریتم Canny:

1- در ابتدا باید تصویر رنگی را به جهت لبه یابی بهتر به یک تصویر سطح خاکسترن تبدیب کرد.

2- نویز را از تصویر دریافتی حذف کرد. بدلیل اینکه فیلتر گاوسین از یک ماسک ساده برای حذف نویز استفاده می کند لبه یاب کنی در مرحله اول برای حذف نویز آن را بکار میگیرد.

3- در یک تصویر سطح خاکستر جایی را که بیشترین تغییرات را داشته باشند به عنوان لبه در نظر گرفته می شوند و این مکانها با گرفتن گرادیان تصویر با استفاده عملگر سوبل بدست می آیند. سپس لبه های مات یافت شده به لبه های تیزتر تبدیل می شوند.

4- برخی از لبه های کشف شده واقعا لبه نیستند و در واقع نویز هستند که باید آنها توسط حد آستانه هیسترزیس فیلتر شوند.هیسترزیس از دو حد آستانه بالاتر (Th) و حد آستانه پایین تر (Tl) استفاده کرده و کنی پیشنهاد می کند که نسبت استانه بالا به پایین سه به یک باشد.

 این روش بیشتر به کشف لبه های ضعیف به درستی می پردازد و کمتر فریب نویز را می خورد و از بقیه روش ها بهتر است.

 

الگوریتم Canny    عملکرد الگوریتم Canny

 

 

 

کد الگوریتم Canny در ++C:

برای الگوریتم Canny دو کد زیر ارائه می شود که کد شماره 2 کد کاملتری است.

کد شماره  الگوریتم 1 الگوریتم Canny در ++C:

در زیر استفاده از الگوریتم کنی در ++C است. توجه داشته باشید که تصویر ابتدا به تصویر سیاه و سفید تبدیل می شود، سپس فیلتر گاوسی برای کاهش نویز در تصویر استفاده می شود. سپس الگوریتم Canny برای تشخیص لبه استفاده می شود.

 

// CannyTutorial.cpp : Defines the entry point for the console application. 
// Environment: Visual studio 2015, Windows 10
// Assumptions: Opecv is installed configured in the visual studio project
// Opencv version: OpenCV 3.1

#include "stdafx.h"
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<string>
#include<iostream>


int main()
{

    //Modified from source: https://github.com/MicrocontrollersAndMore/OpenCV_3_Windows_10_Installation_Tutorial
    cv::Mat imgOriginal;        // input image
    cv::Mat imgGrayscale;        // grayscale of input image
    cv::Mat imgBlurred;            // intermediate blured image
    cv::Mat imgCanny;            // Canny edge image

    std::cout << "Please enter an image filename : ";     std::string img_addr;     std::cin >> img_addr;

    std::cout << "Searching for " + img_addr << std::endl;

    imgOriginal = cv::imread(img_addr);            // open image

    if (imgOriginal.empty()) {                                    // if unable to open image
        std::cout << "error: image not read from file\n\n";        // show error message on command line
        return(0);                                                // and exit program
    }

    cv::cvtColor(imgOriginal, imgGrayscale, CV_BGR2GRAY);        // convert to grayscale

    cv::GaussianBlur(imgGrayscale,            // input image
        imgBlurred,                            // output image
        cv::Size(5, 5),                        // smoothing window width and height in pixels
        1.5);                                // sigma value, determines how much the image will be blurred

    cv::Canny(imgBlurred,            // input image
        imgCanny,                    // output image
        100,                        // low threshold
        200);                        // high threshold


    // Declare windows
    // Note: you can use CV_WINDOW_NORMAL which allows resizing the window
    // or CV_WINDOW_AUTOSIZE for a fixed size window matching the resolution of the image
    // CV_WINDOW_AUTOSIZE is the default
    cv::namedWindow("imgOriginal", CV_WINDOW_AUTOSIZE);        
    cv::namedWindow("imgCanny", CV_WINDOW_AUTOSIZE);

    //Show windows
    cv::imshow("imgOriginal", imgOriginal);        
    cv::imshow("imgCanny", imgCanny);

    cv::waitKey(0);                    // hold windows open until user presses a key
    return 0;
}

 

دانلود کد فوق از طریق لینک زیر:

رمز فایل : behsanandish.com

 

 

کد شماره 2:

مرحله 1: یک blur(تار کننده) گاوسی را اعمال کنید.

اول متغیرهای ضروری اعلام شده اند و بعضی از آنها اولیه هستند. سپس Blur گاوسی اعمال می شود. برای انجام این کار یک ماسک 5×5 بر روی تصویر منتقل می شود. هر پیکسل به صورت مجموع مقادیر پیکسل در محدوده 5×5 آن ضربدر وزن گاوسی متناظر تقسیم شده توسط وزن مجموع کل ماسک تعریف می شود.

 

ماسک گاوسی

ماسک گاوسی

 

#include "stdafx.h"
#include "tripod.h"
#include "tripodDlg.h"

#include "LVServerDefs.h"
#include "math.h"
#include <fstream>
#include <string>
#include <iostream>
#include <stdlib.h>
#include <stdio.h>


#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

using namespace std;

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CTripodDlg dialog

CTripodDlg::CTripodDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CTripodDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CTripodDlg)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

	//////////////// Set destination BMP to NULL first 
	m_destinationBitmapInfoHeader = NULL;

}

////////////////////// Additional generic functions

static unsigned PixelBytes(int w, int bpp)
{
    return (w * bpp + 7) / 8;
}

static unsigned DibRowSize(int w, int bpp)
{
    return (w * bpp + 31) / 32 * 4;
}

static unsigned DibRowSize(LPBITMAPINFOHEADER pbi)
{
    return DibRowSize(pbi->biWidth, pbi->biBitCount);
}

static unsigned DibRowPadding(int w, int bpp)
{
    return DibRowSize(w, bpp) - PixelBytes(w, bpp);
}

static unsigned DibRowPadding(LPBITMAPINFOHEADER pbi)
{
    return DibRowPadding(pbi->biWidth, pbi->biBitCount);
}

static unsigned DibImageSize(int w, int h, int bpp)
{
    return h * DibRowSize(w, bpp);
}

static size_t DibSize(int w, int h, int bpp)
{
    return sizeof (BITMAPINFOHEADER) + DibImageSize(w, h, bpp);
}

/////////////////////// end of generic functions


void CTripodDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CTripodDlg)
	DDX_Control(pDX, IDC_PROCESSEDVIEW, m_cVideoProcessedView);
	DDX_Control(pDX, IDC_UNPROCESSEDVIEW, m_cVideoUnprocessedView);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CTripodDlg, CDialog)
	//{{AFX_MSG_MAP(CTripodDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDEXIT, OnExit)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CTripodDlg message handlers

BOOL CTripodDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { CString strAboutMenu; strAboutMenu.LoadString(IDS_ABOUTBOX); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here

	// For Unprocessed view videoportal (top one)
	char sRegUnprocessedView[] = "HKEY_LOCAL_MACHINE\\Software\\UnprocessedView";
	m_cVideoUnprocessedView.PrepareControl("UnprocessedView", sRegUnprocessedView, 0 );	
	m_cVideoUnprocessedView.EnableUIElements(UIELEMENT_STATUSBAR,0,TRUE);
	m_cVideoUnprocessedView.ConnectCamera2();
	m_cVideoUnprocessedView.SetEnablePreview(TRUE);

	// For binary view videoportal (bottom one)
	char sRegProcessedView[] = "HKEY_LOCAL_MACHINE\\Software\\ProcessedView";
	m_cVideoProcessedView.PrepareControl("ProcessedView", sRegProcessedView, 0 );	
	m_cVideoProcessedView.EnableUIElements(UIELEMENT_STATUSBAR,0,TRUE);
	m_cVideoProcessedView.ConnectCamera2();
	m_cVideoProcessedView.SetEnablePreview(TRUE);

	// Initialize the size of binary videoportal
	m_cVideoProcessedView.SetPreviewMaxHeight(240);
	m_cVideoProcessedView.SetPreviewMaxWidth(320);

	// Uncomment if you wish to fix the live videoportal's size
	// m_cVideoUnprocessedView.SetPreviewMaxHeight(240);
	// m_cVideoUnprocessedView.SetPreviewMaxWidth(320);

	// Find the screen coodinates of the binary videoportal
	m_cVideoProcessedView.GetWindowRect(m_rectForProcessedView);
	ScreenToClient(m_rectForProcessedView);
	allocateDib(CSize(320, 240));

	// Start grabbing frame data for Procssed videoportal (bottom one)
	m_cVideoProcessedView.StartVideoHook(0);

	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CTripodDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CTripodDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CTripodDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CTripodDlg::OnExit() 
{
	// TODO: Add your control notification handler code here

	// Kill live view videoportal (top one)
	m_cVideoUnprocessedView.StopVideoHook(0);
    m_cVideoUnprocessedView.DisconnectCamera();	
	
	// Kill binary view videoportal (bottom one)
	m_cVideoProcessedView.StopVideoHook(0);
    m_cVideoProcessedView.DisconnectCamera();	

	// Kill program
	DestroyWindow();	

	

}

BEGIN_EVENTSINK_MAP(CTripodDlg, CDialog)
    //{{AFX_EVENTSINK_MAP(CTripodDlg)
	ON_EVENT(CTripodDlg, IDC_PROCESSEDVIEW, 1 /* PortalNotification */, OnPortalNotificationProcessedview, VTS_I4 VTS_I4 VTS_I4 VTS_I4)
	//}}AFX_EVENTSINK_MAP
END_EVENTSINK_MAP()

void CTripodDlg::OnPortalNotificationProcessedview(long lMsg, long lParam1, long lParam2, long lParam3) 
{
	// TODO: Add your control notification handler code here
	
	// This function is called at the camera's frame rate
    
#define NOTIFICATIONMSG_VIDEOHOOK	10

	// Declare some useful variables
	// QCSDKMFC.pdf (Quickcam MFC documentation) p. 103 explains the variables lParam1, lParam2, lParam3 too 
	
	LPBITMAPINFOHEADER lpBitmapInfoHeader; // Frame's info header contains info like width and height
	LPBYTE lpBitmapPixelData; // This pointer-to-long will point to the start of the frame's pixel data
    unsigned long lTimeStamp; // Time when frame was grabbed

	switch(lMsg) {
		case NOTIFICATIONMSG_VIDEOHOOK:
			{
				lpBitmapInfoHeader = (LPBITMAPINFOHEADER) lParam1; 
				lpBitmapPixelData = (LPBYTE) lParam2;
				lTimeStamp = (unsigned long) lParam3;

				grayScaleTheFrameData(lpBitmapInfoHeader, lpBitmapPixelData);
				doMyImageProcessing(lpBitmapInfoHeader); // Place where you'd add your image processing code
				displayMyResults(lpBitmapInfoHeader);

			}
			break;

		default:
			break;
	}	
}

void CTripodDlg::allocateDib(CSize sz)
{
	// Purpose: allocate information for a device independent bitmap (DIB)
	// Called from OnInitVideo

	if(m_destinationBitmapInfoHeader) {
		free(m_destinationBitmapInfoHeader);
		m_destinationBitmapInfoHeader = NULL;
	}

	if(sz.cx | sz.cy) {
		m_destinationBitmapInfoHeader = (LPBITMAPINFOHEADER)malloc(DibSize(sz.cx, sz.cy, 24));
		ASSERT(m_destinationBitmapInfoHeader);
		m_destinationBitmapInfoHeader->biSize = sizeof(BITMAPINFOHEADER);
		m_destinationBitmapInfoHeader->biWidth = sz.cx;
		m_destinationBitmapInfoHeader->biHeight = sz.cy;
		m_destinationBitmapInfoHeader->biPlanes = 1;
		m_destinationBitmapInfoHeader->biBitCount = 24;
		m_destinationBitmapInfoHeader->biCompression = 0;
		m_destinationBitmapInfoHeader->biSizeImage = DibImageSize(sz.cx, sz.cy, 24);
		m_destinationBitmapInfoHeader->biXPelsPerMeter = 0;
		m_destinationBitmapInfoHeader->biYPelsPerMeter = 0;
		m_destinationBitmapInfoHeader->biClrImportant = 0;
		m_destinationBitmapInfoHeader->biClrUsed = 0;
	}
}

void CTripodDlg::displayMyResults(LPBITMAPINFOHEADER lpThisBitmapInfoHeader)
{
	// displayMyResults: Displays results of doMyImageProcessing() in the videoport
	// Notes: StretchDIBits stretches a device-independent bitmap to the appropriate size

	CDC				*pDC;	// Device context to display bitmap data
	
	pDC = GetDC();	
	int nOldMode = SetStretchBltMode(pDC->GetSafeHdc(),COLORONCOLOR);

	StretchDIBits( 
		pDC->GetSafeHdc(),
		m_rectForProcessedView.left,				// videoportal left-most coordinate
		m_rectForProcessedView.top,					// videoportal top-most coordinate
		m_rectForProcessedView.Width(),				// videoportal width
		m_rectForProcessedView.Height(),			// videoportal height
		0,											// Row position to display bitmap in videoportal
		0,											// Col position to display bitmap in videoportal
		lpThisBitmapInfoHeader->biWidth,			// m_destinationBmp's number of columns
		lpThisBitmapInfoHeader->biHeight,			// m_destinationBmp's number of rows
		m_destinationBmp,							// The bitmap to display; use the one resulting from doMyImageProcessing
		(BITMAPINFO*)m_destinationBitmapInfoHeader, // The bitmap's header info e.g. width, height, number of bits etc
		DIB_RGB_COLORS,								// Use default 24-bit color table
		SRCCOPY										// Just display
	);
 
	SetStretchBltMode(pDC->GetSafeHdc(),nOldMode);

	ReleaseDC(pDC);

	// Note: 04/24/02 - Added the following:
	// Christopher Wagner cwagner@fas.harvard.edu noticed that memory wasn't being freed

	// Recall OnPortalNotificationProcessedview, which gets called everytime
	// a frame of data arrives, performs 3 steps:
	// (1) grayScaleTheFrameData - which mallocs m_destinationBmp
	// (2) doMyImageProcesing
	// (3) displayMyResults - which we're in now
	// Since we're finished with the memory we malloc'ed for m_destinationBmp
	// we should free it: 
	
	free(m_destinationBmp);

	// End of adds
}

void CTripodDlg::grayScaleTheFrameData(LPBITMAPINFOHEADER lpThisBitmapInfoHeader, LPBYTE lpThisBitmapPixelData)
{

	// grayScaleTheFrameData: Called by CTripodDlg::OnPortalNotificationBinaryview
	// Task: Read current frame pixel data and computes a grayscale version

	unsigned int	W, H;			  // Width and Height of current frame [pixels]
	BYTE            *sourceBmp;		  // Pointer to current frame of data
	unsigned int    row, col;
	unsigned long   i;
	BYTE			grayValue;

	BYTE			redValue;
	BYTE			greenValue;
	BYTE			blueValue;

    W = lpThisBitmapInfoHeader->biWidth;  // biWidth: number of columns
    H = lpThisBitmapInfoHeader->biHeight; // biHeight: number of rows

	// Store pixel data in row-column vector format
	// Recall that each pixel requires 3 bytes (red, blue and green bytes)
	// m_destinationBmp is a protected member and declared in binarizeDlg.h

	m_destinationBmp = (BYTE*)malloc(H*3*W*sizeof(BYTE));

	// Point to the current frame's pixel data
	sourceBmp = lpThisBitmapPixelData;

	for (row = 0; row < H; row++) {
		for (col = 0; col < W; col++) { // Recall each pixel is composed of 3 bytes i = (unsigned long)(row*3*W + 3*col); // The source pixel has a blue, green andred value: blueValue = *(sourceBmp + i); greenValue = *(sourceBmp + i + 1); redValue = *(sourceBmp + i + 2); // A standard equation for computing a grayscale value based on RGB values grayValue = (BYTE)(0.299*redValue + 0.587*greenValue + 0.114*blueValue); // The destination BMP will be a grayscale version of the source BMP *(m_destinationBmp + i) = grayValue; *(m_destinationBmp + i + 1) = grayValue; *(m_destinationBmp + i + 2) = grayValue; } } } void CTripodDlg::doMyImageProcessing(LPBITMAPINFOHEADER lpThisBitmapInfoHeader) { // doMyImageProcessing: This is where you'd write your own image processing code // Task: Read a pixel's grayscale value and process accordingly unsigned int W, H; // Width and Height of current frame [pixels] unsigned int row, col; // Pixel's row and col positions unsigned long i; // Dummy variable for row-column vector int upperThreshold = 60; // Gradient strength nessicary to start edge int lowerThreshold = 30; // Minimum gradient strength to continue edge unsigned long iOffset; // Variable to offset row-column vector during sobel mask int rowOffset; // Row offset from the current pixel int colOffset; // Col offset from the current pixel int rowTotal = 0; // Row position of offset pixel int colTotal = 0; // Col position of offset pixel int Gx; // Sum of Sobel mask products values in the x direction int Gy; // Sum of Sobel mask products values in the y direction float thisAngle; // Gradient direction based on Gx and Gy int newAngle; // Approximation of the gradient direction bool edgeEnd; // Stores whether or not the edge is at the edge of the possible image int GxMask[3][3]; // Sobel mask in the x direction int GyMask[3][3]; // Sobel mask in the y direction int newPixel; // Sum pixel values for gaussian int gaussianMask[5][5]; // Gaussian mask W = lpThisBitmapInfoHeader->biWidth;  // biWidth: number of columns
    H = lpThisBitmapInfoHeader->biHeight; // biHeight: number of rows
	
	for (row = 0; row < H; row++) {
		for (col = 0; col < W; col++) {
			edgeDir[row][col] = 0;
		}
	}

	/* Declare Sobel masks */
	GxMask[0][0] = -1; GxMask[0][1] = 0; GxMask[0][2] = 1;
	GxMask[1][0] = -2; GxMask[1][1] = 0; GxMask[1][2] = 2;
	GxMask[2][0] = -1; GxMask[2][1] = 0; GxMask[2][2] = 1;
	
	GyMask[0][0] =  1; GyMask[0][1] =  2; GyMask[0][2] =  1;
	GyMask[1][0] =  0; GyMask[1][1] =  0; GyMask[1][2] =  0;
	GyMask[2][0] = -1; GyMask[2][1] = -2; GyMask[2][2] = -1;

	/* Declare Gaussian mask */
	gaussianMask[0][0] = 2;		gaussianMask[0][1] = 4;		gaussianMask[0][2] = 5;		gaussianMask[0][3] = 4;		gaussianMask[0][4] = 2;	
	gaussianMask[1][0] = 4;		gaussianMask[1][1] = 9;		gaussianMask[1][2] = 12;	gaussianMask[1][3] = 9;		gaussianMask[1][4] = 4;	
	gaussianMask[2][0] = 5;		gaussianMask[2][1] = 12;	gaussianMask[2][2] = 15;	gaussianMask[2][3] = 12;	gaussianMask[2][4] = 2;	
	gaussianMask[3][0] = 4;		gaussianMask[3][1] = 9;		gaussianMask[3][2] = 12;	gaussianMask[3][3] = 9;		gaussianMask[3][4] = 4;	
	gaussianMask[4][0] = 2;		gaussianMask[4][1] = 4;		gaussianMask[4][2] = 5;		gaussianMask[4][3] = 4;		gaussianMask[4][4] = 2;	
	

	/* Gaussian Blur */
	for (row = 2; row < H-2; row++) {
		for (col = 2; col < W-2; col++) {
			newPixel = 0;
			for (rowOffset=-2; rowOffset<=2; rowOffset++) {
				for (colOffset=-2; colOffset<=2; colOffset++) {
					rowTotal = row + rowOffset;
					colTotal = col + colOffset;
					iOffset = (unsigned long)(rowTotal*3*W + colTotal*3);
					newPixel += (*(m_destinationBmp + iOffset)) * gaussianMask[2 + rowOffset][2 + colOffset];
				}
			}
			i = (unsigned long)(row*3*W + col*3);
			*(m_destinationBmp + i) = newPixel / 159;
		}
	}

	/* Determine edge directions and gradient strengths */
	for (row = 1; row < H-1; row++) {
		for (col = 1; col < W-1; col++) {
			i = (unsigned long)(row*3*W + 3*col);
			Gx = 0;
			Gy = 0;
			/* Calculate the sum of the Sobel mask times the nine surrounding pixels in the x and y direction */
			for (rowOffset=-1; rowOffset<=1; rowOffset++) {
				for (colOffset=-1; colOffset<=1; colOffset++) {
					rowTotal = row + rowOffset;
					colTotal = col + colOffset;
					iOffset = (unsigned long)(rowTotal*3*W + colTotal*3);
					Gx = Gx + (*(m_destinationBmp + iOffset) * GxMask[rowOffset + 1][colOffset + 1]);
					Gy = Gy + (*(m_destinationBmp + iOffset) * GyMask[rowOffset + 1][colOffset + 1]);
				}
			}

			gradient[row][col] = sqrt(pow(Gx,2.0) + pow(Gy,2.0));	// Calculate gradient strength			
			thisAngle = (atan2(Gx,Gy)/3.14159) * 180.0;		// Calculate actual direction of edge
			
			/* Convert actual edge direction to approximate value */
			if ( ( (thisAngle < 22.5) && (thisAngle > -22.5) ) || (thisAngle > 157.5) || (thisAngle < -157.5) ) newAngle = 0; if ( ( (thisAngle > 22.5) && (thisAngle < 67.5) ) || ( (thisAngle < -112.5) && (thisAngle > -157.5) ) )
				newAngle = 45;
			if ( ( (thisAngle > 67.5) && (thisAngle < 112.5) ) || ( (thisAngle < -67.5) && (thisAngle > -112.5) ) )
				newAngle = 90;
			if ( ( (thisAngle > 112.5) && (thisAngle < 157.5) ) || ( (thisAngle < -22.5) && (thisAngle > -67.5) ) )
				newAngle = 135;
				
			edgeDir[row][col] = newAngle;		// Store the approximate edge direction of each pixel in one array
		}
	}

	/* Trace along all the edges in the image */
	for (row = 1; row < H - 1; row++) {
		for (col = 1; col < W - 1; col++) { edgeEnd = false; if (gradient[row][col] > upperThreshold) {		// Check to see if current pixel has a high enough gradient strength to be part of an edge
				/* Switch based on current pixel's edge direction */
				switch (edgeDir[row][col]){		
					case 0:
						findEdge(0, 1, row, col, 0, lowerThreshold);
						break;
					case 45:
						findEdge(1, 1, row, col, 45, lowerThreshold);
						break;
					case 90:
						findEdge(1, 0, row, col, 90, lowerThreshold);
						break;
					case 135:
						findEdge(1, -1, row, col, 135, lowerThreshold);
						break;
					default :
						i = (unsigned long)(row*3*W + 3*col);
						*(m_destinationBmp + i) = 
						*(m_destinationBmp + i + 1) = 
						*(m_destinationBmp + i + 2) = 0;
						break;
					}
				}
			else {
				i = (unsigned long)(row*3*W + 3*col);
					*(m_destinationBmp + i) = 
					*(m_destinationBmp + i + 1) = 
					*(m_destinationBmp + i + 2) = 0;
			}	
		}
	}
	
	/* Suppress any pixels not changed by the edge tracing */
	for (row = 0; row < H; row++) {
		for (col = 0; col < W; col++) {	
			// Recall each pixel is composed of 3 bytes
			i = (unsigned long)(row*3*W + 3*col);
			// If a pixel's grayValue is not black or white make it black
			if( ((*(m_destinationBmp + i) != 255) && (*(m_destinationBmp + i) != 0)) || ((*(m_destinationBmp + i + 1) != 255) && (*(m_destinationBmp + i + 1) != 0)) || ((*(m_destinationBmp + i + 2) != 255) && (*(m_destinationBmp + i + 2) != 0)) ) 
				*(m_destinationBmp + i) = 
				*(m_destinationBmp + i + 1) = 
				*(m_destinationBmp + i + 2) = 0; // Make pixel black
		}
	}

	/* Non-maximum Suppression */
	for (row = 1; row < H - 1; row++) {
		for (col = 1; col < W - 1; col++) {
			i = (unsigned long)(row*3*W + 3*col);
			if (*(m_destinationBmp + i) == 255) {		// Check to see if current pixel is an edge
				/* Switch based on current pixel's edge direction */
				switch (edgeDir[row][col]) {		
					case 0:
						suppressNonMax( 1, 0, row, col, 0, lowerThreshold);
						break;
					case 45:
						suppressNonMax( 1, -1, row, col, 45, lowerThreshold);
						break;
					case 90:
						suppressNonMax( 0, 1, row, col, 90, lowerThreshold);
						break;
					case 135:
						suppressNonMax( 1, 1, row, col, 135, lowerThreshold);
						break;
					default :
						break;
				}
			}	
		}
	}
	
}

void CTripodDlg::findEdge(int rowShift, int colShift, int row, int col, int dir, int lowerThreshold)
{
	int W = 320;
	int H = 240;
	int newRow;
	int newCol;
	unsigned long i;
	bool edgeEnd = false;

	/* Find the row and column values for the next possible pixel on the edge */
	if (colShift < 0) { if (col > 0)
			newCol = col + colShift;
		else
			edgeEnd = true;
	} else if (col < W - 1) {
		newCol = col + colShift;
	} else
		edgeEnd = true;		// If the next pixel would be off image, don't do the while loop
	if (rowShift < 0) { if (row > 0)
			newRow = row + rowShift;
		else
			edgeEnd = true;
	} else if (row < H - 1) { newRow = row + rowShift; } else edgeEnd = true; /* Determine edge directions and gradient strengths */ while ( (edgeDir[newRow][newCol]==dir) && !edgeEnd && (gradient[newRow][newCol] > lowerThreshold) ) {
		/* Set the new pixel as white to show it is an edge */
		i = (unsigned long)(newRow*3*W + 3*newCol);
		*(m_destinationBmp + i) =
		*(m_destinationBmp + i + 1) =
		*(m_destinationBmp + i + 2) = 255;
		if (colShift < 0) { if (newCol > 0)
				newCol = newCol + colShift;
			else
				edgeEnd = true;	
		} else if (newCol < W - 1) {
			newCol = newCol + colShift;
		} else
			edgeEnd = true;	
		if (rowShift < 0) { if (newRow > 0)
				newRow = newRow + rowShift;
			else
				edgeEnd = true;
		} else if (newRow < H - 1) {
			newRow = newRow + rowShift;
		} else
			edgeEnd = true;	
	}	
}

void CTripodDlg::suppressNonMax(int rowShift, int colShift, int row, int col, int dir, int lowerThreshold)
{
	int W = 320;
	int H = 240;
	int newRow = 0;
	int newCol = 0;
	unsigned long i;
	bool edgeEnd = false;
	float nonMax[320][3];			// Temporarily stores gradients and positions of pixels in parallel edges
	int pixelCount = 0;					// Stores the number of pixels in parallel edges
	int count;						// A for loop counter
	int max[3];						// Maximum point in a wide edge
	
	if (colShift < 0) { if (col > 0)
			newCol = col + colShift;
		else
			edgeEnd = true;
	} else if (col < W - 1) {
		newCol = col + colShift;
	} else
		edgeEnd = true;		// If the next pixel would be off image, don't do the while loop
	if (rowShift < 0) { if (row > 0)
			newRow = row + rowShift;
		else
			edgeEnd = true;
	} else if (row < H - 1) {
		newRow = row + rowShift;
	} else
		edgeEnd = true;	
	i = (unsigned long)(newRow*3*W + 3*newCol);
	/* Find non-maximum parallel edges tracing up */
	while ((edgeDir[newRow][newCol] == dir) && !edgeEnd && (*(m_destinationBmp + i) == 255)) {
		if (colShift < 0) { if (newCol > 0)
				newCol = newCol + colShift;
			else
				edgeEnd = true;	
		} else if (newCol < W - 1) {
			newCol = newCol + colShift;
		} else
			edgeEnd = true;	
		if (rowShift < 0) { if (newRow > 0)
				newRow = newRow + rowShift;
			else
				edgeEnd = true;
		} else if (newRow < H - 1) {
			newRow = newRow + rowShift;
		} else
			edgeEnd = true;	
		nonMax[pixelCount][0] = newRow;
		nonMax[pixelCount][1] = newCol;
		nonMax[pixelCount][2] = gradient[newRow][newCol];
		pixelCount++;
		i = (unsigned long)(newRow*3*W + 3*newCol);
	}

	/* Find non-maximum parallel edges tracing down */
	edgeEnd = false;
	colShift *= -1;
	rowShift *= -1;
	if (colShift < 0) { if (col > 0)
			newCol = col + colShift;
		else
			edgeEnd = true;
	} else if (col < W - 1) {
		newCol = col + colShift;
	} else
		edgeEnd = true;	
	if (rowShift < 0) { if (row > 0)
			newRow = row + rowShift;
		else
			edgeEnd = true;
	} else if (row < H - 1) {
		newRow = row + rowShift;
	} else
		edgeEnd = true;	
	i = (unsigned long)(newRow*3*W + 3*newCol);
	while ((edgeDir[newRow][newCol] == dir) && !edgeEnd && (*(m_destinationBmp + i) == 255)) {
		if (colShift < 0) { if (newCol > 0)
				newCol = newCol + colShift;
			else
				edgeEnd = true;	
		} else if (newCol < W - 1) {
			newCol = newCol + colShift;
		} else
			edgeEnd = true;	
		if (rowShift < 0) { if (newRow > 0)
				newRow = newRow + rowShift;
			else
				edgeEnd = true;
		} else if (newRow < H - 1) {
			newRow = newRow + rowShift;
		} else
			edgeEnd = true;	
		nonMax[pixelCount][0] = newRow;
		nonMax[pixelCount][1] = newCol;
		nonMax[pixelCount][2] = gradient[newRow][newCol];
		pixelCount++;
		i = (unsigned long)(newRow*3*W + 3*newCol);
	}

	/* Suppress non-maximum edges */
	max[0] = 0;
	max[1] = 0;
	max[2] = 0;
	for (count = 0; count < pixelCount; count++) { if (nonMax[count][2] > max[2]) {
			max[0] = nonMax[count][0];
			max[1] = nonMax[count][1];
			max[2] = nonMax[count][2];
		}
	}
	for (count = 0; count < pixelCount; count++) {
		i = (unsigned long)(nonMax[count][0]*3*W + 3*nonMax[count][1]);
		*(m_destinationBmp + i) = 
		*(m_destinationBmp + i + 1) = 
		*(m_destinationBmp + i + 2) = 0;
	}
}

الگوریتم Canny در سی پلاس پلاس قسمت 1
الگوریتم Canny در سی پلاس پلاس قسمت 2
الگوریتم Canny در سی پلاس پلاس قسمت 3
الگوریتم Canny در سی پلاس پلاس فسمت 4

الگوریتم Canny

لبه یاب کنی توسط جان اف کنی در سال 1986 ایجاد شد و هنوز یک لبه یاب استاندارد و با دقت و کیفیت بالا میباشد.الگوریتم لبه یابی کنی یکی از بهترین لبه یابها تا به امروز است. در ادامه روش کار این الگوریتم و هم چنین کد الگوریتم Canny در OpenCV را بررسی خواهیم کرد. این الگوریتم لبه یابی از سه بخش اصلی زیر تشکیل شده:

  • تضعیف نویز
  • پیدا کردن نقاطی که بتوان آنها را به عنوان لبه در نظر گرفت
  • حذب نقاطی که احتمال لبه بودن آنها کم است

 

معیارهایی که در لبه یاب کنی مطرح است:
1 -پایین آوردن نرخ خطا- یعنی تا حد امکان هیچ لبه ای در تصویر نباید گم شود و هم چنین هیچ چیزی که لبه نیست نباید به جای لبه فرض شود. لبه هان پیدا شده تا حد ممکن به لبه ها اصلی
نزدیک باشند.

2 -لبه در مکان واقعی خود باشد- یعنی تا حد ممکن لبه ها کمترین فاصله را با مکان واقعی خود داشته باشند.
3 -بران هر لبه فقط یک پاسخ داشته باشیم.

4 -لبه ها کمترین ضخامت را داشته باشند- (در صورت امکان یک پیکسل).
لبه یاب کنی بخاطر توانایی در تولید لبه های نازک تا حد یک ییکسل برای لبه های پیوسته معروف شده است. این لبه یاب شامل چهار مرحله و چهار ورودی زیر است:
یک تصویر ورودی
یک پارامتر به نام سیگما جهت مقدار نرم کنندگی تصویر
یک حد آستانه بالا (Th)
یک حد آستانه پایین (Tl)

 

مراحل الگوریتم Canny:

1- در ابتدا باید تصویر رنگی را به جهت لبه یابی بهتر به یک تصویر سطح خاکسترن تبدیب کرد.

2- نویز را از تصویر دریافتی حذف کرد. بدلیل اینکه فیلتر گاوسین از یک ماسک ساده برای حذف نویز استفاده می کند لبه یاب کنی در مرحله اول برای حذف نویز آن را بکار میگیرد.

3- در یک تصویر سطح خاکستر جایی را که بیشترین تغییرات را داشته باشند به عنوان لبه در نظر گرفته می شوند و این مکانها با گرفتن گرادیان تصویر با استفاده عملگر سوبل بدست می آیند. سپس لبه های مات یافت شده به لبه های تیزتر تبدیل می شوند.

4- برخی از لبه های کشف شده واقعا لبه نیستند و در واقع نویز هستند که باید آنها توسط حد آستانه هیسترزیس فیلتر شوند.هیسترزیس از دو حد آستانه بالاتر (Th) و حد آستانه پایین تر (Tl) استفاده کرده و کنی پیشنهاد می کند که نسبت استانه بالا به پایین سه به یک باشد.

 این روش بیشتر به کشف لبه های ضعیف به درستی می پردازد و کمتر فریب نویز را می خورد و از بقیه روش ها بهتر است.

 

 

الگوریتم Canny    عملکرد الگوریتم Canny

 

کد الگوریتم Canny در OpenCV:

 

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <stdlib.h>
#include <stdio.h>

using namespace cv;

/// Global variables

Mat src, src_gray;
Mat dst, detected_edges;

int edgeThresh = 1;
int lowThreshold;
int const max_lowThreshold = 100;
int ratio = 3;
int kernel_size = 3;
char* window_name = "Edge Map";

/**
 * @function CannyThreshold
 * @brief Trackbar callback - Canny thresholds input with a ratio 1:3
 */
void CannyThreshold(int, void*)
{
  /// Reduce noise with a kernel 3x3
  blur( src_gray, detected_edges, Size(3,3) );

  /// Canny detector
  Canny( detected_edges, detected_edges, lowThreshold, lowThreshold*ratio, kernel_size );

  /// Using Canny's output as a mask, we display our result
  dst = Scalar::all(0);

  src.copyTo( dst, detected_edges);
  imshow( window_name, dst );
 }

/** @function main */
int main( int argc, char** argv )
{
  /// Load an image
  src = imread( argv[1] );

  if( !src.data )
  { return -1; }</pre>
<pre>  /// Create a matrix of the same type and size as src (for dst)
  dst.create( src.size(), src.type() );

  /// Convert the image to grayscale
  cvtColor( src, src_gray, CV_BGR2GRAY );

  /// Create a window
  namedWindow( window_name, CV_WINDOW_AUTOSIZE );

  /// Create a Trackbar for user to enter threshold
  createTrackbar( "Min Threshold:", window_name, &lowThreshold, max_lowThreshold, CannyThreshold );

  /// Show the image
  CannyThreshold(0, 0);

  /// Wait until user exit program by pressing a key
  waitKey(0);

  return 0;
  }

 

 

دانلود کد فوق از طریق لینک زیر:

CannyInOpenCV

رمز فایل : behsanandish.com

 

تشخیص پلاک خودرو

چکیده– شماره پلاک خودرو یکی از مناسب ترین اقلام اطلاعات جهت احراز هویت خودروها می باشد.سامانه تشخیص پلاک خودرو یک سیستم کاملاً مکانیزه است. در این مقاله به بررسی و نحوه کار یک سیستم اتوماتیک تشخیص پلاک میپردازیم که امروزه نمی توان کاربرد مفید و چشمگیر آن را نادیده گرفت. این سیستم با استفاده از پردازش تصویر خودروهای عبوری از یک مکان، شماره پلاک آنها را استخراج کرده و به صورت عددی مورد استفاده قرار می دهد.

کلمات کلیدی– تشخیص پلاک خودرو، تشخیص کاراکتر نوری، پردازش تصویر، OCR

فایل PDF – در 7 صفحه- نویسنده : مریم زارع

تشخیص پلاک خودرو

پسورد فایل : behsanandish.com


تشخیص اتوماتیک پلاک خودرو فارسی به کمک روش های پردازش تصویر و شبکه های عصبی

چکیده- شماره پلاک خودرو یکی از مناسب ترین اقلام اطلاعاتی جهت احراز هویت خودروها می باشد. سیستم تشخیص پلاک خودرو یک سیستم مکانیزه است که با عکس گرفتن از خودروها، شماره پلاک آنها را استخراج می کند.روشی که در این مقاله استفاده شده شامل دو قسمت می باشد. در قسمت اول با استفاده از لبه یابی و عملیات مورفولوژی محل پلاک شناسایی شده و در قسمت دوم با استفاده از شبکه عصبی هاپفیلد کاراکترها شناسایی می شوند. این روش بر روی 500 تصویر مختلف از نظر پس زمینه، فاصله و زاویه دید مورد آزمایش قرار گرفته است، که نرخ استخراج صحیح پلاک را 95% و همچنین نرخ خواندن صحیح پلاک را 90% بدست آوردیم.

کلمات کلیدی– تشخیص پلاک خودرو، شبکه عصبی هاپفیلد، عملیات مورفولوژی، لبه یابی، هیستوگرام.

فایل PDF – در 8 صفحه- نویسندگان : محمدصادق معمارزاده، همایون مهدوی نسب، پیمان معلم.

تشخیص اتوماتیک پلاک خودرو فارسی به کمک روش های پردازش تصویر و شبکه عصبی

پسورد فایل : behsanandish.com


روش ﺟﺪﯾﺪ ﻣﮑﺎنﯾﺎﺑﯽ ﭘﻼك ﺧﻮدرو در ﺗﺼﺎوﯾﺮ رﻧﮕﯽ

ﭼﮑﯿﺪه – اﯾﻦ ﻣﻘﺎﻟه روش ﺟدﯾﺪی ﺟﻬﺖ ﻣﮑﺎنﯾﺎﺑﯽ ﭘﻼك ﺧﻮدرو اراﺋﻪ میﮐﻨﺪ. روش پیشنهادی ﺑﻪ ﻋﻠﺖ ﻋﺪم اﺳﺘﻔﺎده از  عملیاتﻫﺎي ﭘﺮﻫﺰﯾﻨﻪ ﭘﺮدازش ﺗﺼﻮﯾﺮ، داراي ﺳﺮﻋﺖ پاسخگویی ﺑﺎلاتري نسبت ﺑﻪ روشﻫﺎی ﻣﺸﺎﺑﻪ اﺳﺖ. روش ﭘﯿﺸﻨﻬﺎدي در اﯾﻦ ﻣﻘﺎﻟﻪ، ﻣﺒﺘﻨﯽ ﺑﺮ ﺷﻨﺎﺳﺎﯾﯽ اﻟﮕﻮ و ﺑﻮده و ﺑﺎ اﺳﺘﻔﺎده از پیمایش ﺳﺘﻮﻧﯽ ﺑﺮاي ﯾﺎﻓﺘﻦ اﻟﮕﻮﯾﯽ اﺳﺘﺎﻧﺪارد در ﺗﺼﻮﯾﺮ رنگی، ﭘﻼك ﺧﻮدرو را ﻣﮑﺎن یابی و آن را از تصویر اﺳﺘﺨﺮاج می کند. از ﺧﺼﻮﺻﯿﺎت روش ﻣﺬﮐﻮر، ﺳﺮﻋﺖ ﺑﺎلای ﭘﺮدازش و ﭘﺎﺳﺦ گویی ﺳﺮﯾﻊ، قابلیت ﻧﺼﺐ و اﺟـﺮ در ریزپردازنده ها، ﻗﺎبلیت شناسایی چندین پلاک ﻣﻮﺟﻮد دریک تصویر و پردازش بر روی تصویر رنگی بدون تغییر اندازه ی آن، ﻣﯽﺑﺎﺷﺪ. روش اراﺋﻪ ﺷﺪه، دارای کاربردهای عملی از قبیل صدور برگ جریمه الکترونیکی، اﯾﺠﺎد ﺳﺎﻣﺎﻧﮥ ﻫﻮﺷﻤﻨﺪ ﭘﺮداﺧﺖ ﻋﻮارض، کنترل ﺗﻮﻧﻞ ﻫﺎ، بزرگراه ها، پارکینگ ها، ﻣﺤﺪوده ﻃﺮح ترافیک و ﻏﯿﺮه، ﻣﯽﺑﺎﺷﺪ. ﻧﺘﺎﯾﺞ آزﻣﺎﯾﺸﺎت ﺑﺮ روي ﯾﮏ ﻣﺠﻤﻮﻋﻪ داده دﻟﺨﻮاه از ﺗﺼﺎوﯾﺮ دورﺑﯿﻦﻫﺎي ﮐﻨﺘﺮل ﺳﺮﻋﺖ در ﺑﺰرﮔﺮاه ﻫﺎي ﮐﺸﻮر، ﮐﺎراﯾﯽ، دﻗﺖ، اﻃﻤﯿﻨﺎن و ﺳﺮﻋﺖ ﺳﯿﺴﺘﻢ ﭘﯿﺸﻨﻬﺎدي را ﺗﺎﯾﯿﺪ ﮐﺮد ﺑﻪ ﻃﻮري ﮐﻪ در آزﻣﺎﯾﺸﺎت  دﻗـﺖ تشخیص 96 درصد را به خود اختصاص داده است.

کلمات کلیدی– مکان یابی پلاک خودرو، تشخیص پلاک خودرو، شناسایی الگو.

فایل PDF – در 6 صفحه- نویسندگان : امیرحسین اشتری و محمود فتحی.

روش جدید مکانیابی پلاك خودرو در تصاویر رنگی

پسورد فایل : behsanandish.com


شرکت بهسان اندیش تولید کننده سامانه های هوشمند مفتخر به تولید یکی از دقیقترین و سریعترین سامانه های جامع کنترل تردد خودرو می باشد که می توانید جهت آشنایی با قابلیت ها و امکانات این محصول به لینک :سامانه جامع کنترل تردد خودرو بهسان(پلاک خوان) مراجعه فرمایید.


ﺭﻭﺷﯽ ﺟﺪﻳﺪ ﻭ ﺳﺮﻳﻊ ﺑﺮﺍﯼ ﺗﺸﺨﻴﺺ ﻣﺤﻞ ﭘﻼﮎ ﺧﻮﺩﺭﻭ ﺍﺯ ﺗﺼﺎﻭﻳﺮ ﭘﻴﭽﻴﺪﻩ ﺑﺮ ﺍﺳﺎﺱ ﻋﻤﻠﻴﺎﺕ ﻣﻮﺭﻓﻮﻟﻮﮊﻳﮑﯽ

 ﭼﮑﻴﺪﻩ – ﺗﺸﺨﻴﺺ ﻣﺤﻞ ﭘﻼﮎ ﺧﻮﺩﺭو ﻣﻬﻤﺘﺮﻳﻦ ﻣﺮﺣﻠﻪ ﺷﻨﺎﺳﺎﻳﯽ ﭘﻼک ﺧﻮﺩﺭو ﺩﺭ ﺳﻴﺴﺘﻤﻬﺎﯼ حمل ﻭ ﻧﻘﻞ هوشمند ﺍﺳﺖ . ﺩﺭ ﺍﻳﻦ ﻣﻘﺎﻟﻪ روشی  بلادرنگ ﻭ ﺳﺮﻳﻊ ﺑﺮﺍﯼ ﭘﻴﺪﺍ ﮐﺮﺩﻥ ﭘﻼﮎ ﺧﻮﺩﺭﻭﻫﺎ ﺩﺭ ﺗﺼﺎﻭﻳﺮ ﭘﻴﭽﻴﺪﻩ ﻣﻌﺮﻓﯽ ﻣﯽ شود. ﺩﺭ ﺍﻟﮕﻮﺭﻳﺘﻢ ﭘﻴﺸﻨﻬﺎﺩﯼ ﺍﺑﺘﺪﺍ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ ﻋﻤﻠﮕﺮ ﺳﻮﺑﻞ ﺍﻗﺪﺍﻡ ﺑﻪ ﻳﺎﻓﺘﻦ لبه ﻫﺎﯼ ﻋﻤﻮﺩﯼ ﺗﺼﻮﻳﺮ می ﮐﻨﻴﻢ، ﺳﭙﺲ ﺑﺎ ﺍﺳﺘﻔﺎﺩﻩ ﺍﺯ تحلیل ﻫﻴﺴﺘﻮﮔﺮﺍﻡ ﻭ ﺗﺮﮐﻴﺒﯽ ﺍﺯ ﻋﻤﻠﮕﺮﻫﺎﯼ ﻣﻮﺭﻓﻮﻟﻮﮊیکی ﭘﻼک ﺧﻮﺩﺭﻭ ﺭﺍ ﺍﺯ ﺗﺼﻮﻳﺮ ﺍﺳﺘﺨﺮﺍﺝ می کنیم.ﺭﻭﺵ ﭘﻴﺸﻨﻬﺎﺩﯼ را ﺭﻭﯼ پاﻳﮕﺎﻩ ﺩﺍﺩﻩ ﺍﯼ ﺷﺎﻣﻞ 300 ﺗﺼﻮﻳﺮ ﻣﺨﺘﻠﻒ ﺍﺯ نظر ﭘﺲ ﺯﻣﻴﻨﻪ، ﺍﻧﺪﺍﺯﻩ، ﻓﺎﺻﻠﻪ، ﺯﺍﻭﻳﻪ ﺩﻳﺪ ﻭ ﺷﺮﺍﻳﻂ ﻧﻮﺭی ﻣﻮﺭﺩ ﺁﺯﻣﺎﻳﺶ ﻗﺮﺍﺭ ﺩﺍﺩﻩ ﻭ ﻧﺮﺥ ﺍﺳﺘﺨﺮﺍﺝ ﺻﺤﻴﺢ ﭘﻼﮎ  را 81/3% بدست آوردیم.
کلمات کلیدی– تشخیص محل، پلاک خودرو، ﻫﻴﺴﺘﻮﮔﺮﺍﻡ، ﻋﻤﻠﻴﺎﺕ ﻣﻮﺭﻓﻮﻟﻮﮊﻳﮑﯽ.
فایل PDF – در 7 صفحه- نویسندگان : فرهاد فرجی و رضا صفابخش

ﺭﻭﺷﯽ ﺟﺪﻳﺪ ﻭ ﺳﺮﻳﻊ ﺑﺮﺍﯼ ﺗﺸﺨﻴﺺ ﻣﺤﻞ ﭘﻼﮎ ﺧﻮﺩﺭﻭ ﺍﺯ ﺗﺼﺎﻭﻳﺮ ﭘﻴﭽﻴﺪﻩ ﺑﺮ ﺍﺳﺎﺱ ﻋﻤﻠﻴﺎﺕ ﻣﻮﺭﻓﻮﻟﻮﮊﻳﮑﯽ

پسورد فایل : behsanandish.com


شناسایی پلاک خودروهای ایرانی با روش جایابی فازی پلاک

چکیده– یکی از مهم ترین زیرسامانه های حمل و نقل هوشمند، سامانه ی تشخیص و شناسایی پلاک خودرو است. دشواری تشخیص و شناسایی صحیح پلاک خودرو در شرایط مختلف محیطی موجب شده تا پژوهش در این زمینه ی پژوهشی هم چنان ادامه داشته باشد. مسئله ی تشخیص پلاک خودرو را می توان به سه زیر مسئله ی “جایابی پلاک”، “استخراج نویسه های پلاک” و “شناسایی نویسه ها” تقسیم کرد. در این مقاله تلاش شده به کمک قواعد فازی، الگوریتم های جایابی پلاک خودروهای ایرانی و شناسایی نویسه های آن بهبود یابد. جایابی پلاک با لبه یابی، تحلیل ریخت شناسانه و استفاده از قواعد فازی و شناسایی نویسه ها با استفاده از ماشین بردار پشتیبانی فازی انجام شده است. با آزمایش الگوریتم یاد شده بر روی پنجاه تصویر صحت جایابی پلاک خودرو 90 درصد و صحت شناسایی نویسه ها 94 درصد به دست آمد که در مقایسه با روش های مرسوم توانمندی چشمگیری دارد.

کلمات کلیدی– پلاک خودروف شناسایی الگو، ماشین بردار پشتیبانی، نظریه ی فازی.

فایل PDF – در 10 صفحه- نویسندگان : غلامعلی منتظر و محمد شایسته فر

شناسایی پلاک خودروهای ایرانی با روش جایابی فازی پلاک

پسورد فایل : behsanandish.com


Vehicle License Plate Identification & Recognition

شناسایی و به رسمیت شناختن شماره پلاک خودرو

Abstract- Existing vehicle license plate identification and recognition systems are potent for either their accuracy
or speed but not a combination of both. The algorithm proposed in this dissertation attempts to achieve
this fine balance between the accuracy and speed that such a system must posses. The mathematical
morphology operators of dilation and erosion are utilized to identify the region within an image which
contains the license plate. Using the concept of color coherence vectors, an image recognition algorithm
is presented which utilizes this extracted region and compares it as a whole to other images of license
plates, in the database. The application developed for the testing of this algorithm works with an
accuracy of eighty eight percent and an average processing time of two seconds per image.
Key Words and Phrases: Vehicle license plate recognition, color coherence vectors, mathematical
morphology

فایل PDF – در 10 صفحه- نویسندگان : SANJAY GOEL, PRIYANK SINGH

Vehicle License Plate Identification & Recognition

پسورد فایل : behsanandish.com


Sensor network based vehicle classification and license plate identification system

طبقه بندی وسایل نقلیه بر اساس شبکه حسگر و سیستم شناسایی پلاک وسایل نقلیه

Abstract—Typically, for energy efficiency and scalability purposes, sensor networks have been used in the context of environmental and traffic monitoring applications in which operations at the sensor level are not computationally intensive. But increasingly, sensor network applications require data and compute intensive sensors such video cameras and microphones. In this paper, we describe the design and implementation of two such systems: a vehicle classifier based on acoustic signals and a license plate identification system using a camera. The systems are implemented in an energy-efficient manner to the extent possible using commercially available hardware, the Mica motes and the Stargate platform. Our experience in designing these systems leads us to consider an alternate more flexible, modular, low-power mote architecture that uses a combination of FPGAs, specialized embedded processing units and sensor data acquisition systems.
Keywords: wireless sensor networks, seismic, acoustic vehicle classification, license plate detection

فایل PDF – در 4 صفحه- نویسندگان :Jan Frigo, Vinod Kulathumani, Sean Brennan∗, Ed Rosten, Eric Raby

Sensor network based vehicle classification and

پسورد فایل : behsanandish.com


Real Time Automatic License Plate Recognition in Video Streams

تشخیص خودکار زمان واقعی شماره پلاک وسایل نقلیه در جریان های ویدیویی

Abstract
In recent years there has been an increased commercial interest in systems for automatic license plate recognition. Some of the existing systems process single images only, some even requiring vehicles to stop in front of a gate so that a still image of good quality can be taken. This thesis presents an approach that makes it possible to process 25 images per second on a standard PC from 2004, allowing identication decisions to be based on information from several images instead of just a single one. Thus, the impact of a single bad image is reduced, and vehicles can be allowed to drive past the camera without hindrance. In order to reach the necessary processing speed, a simplied StauerGrimson background estimation algorithm has been used, enabling the system to only search for license plates on objects that are in motion. The main method for nding license plates has been a computational-wise economical connected component labeling algorithm. A basic pixel-by-pixel comparison OCR algorithm %has also been implemented. A real life test running for twelve days has shown the complete system to have a rate of successful identification at 80 .

فایل PDF – در 28 صفحه- نویسنده : Fredrik Trobro

Real Time Automatic License Plate Recognition

پسورد فایل : behsanandish.com


Proposal for Automatic License and Number Plate Recognition System for Vehicle Identification

طرح پیشنهادی برای سیستم شناسایی خودکار شماره پلاک و مجوز برای شناسایی خودرو

Abstract— In this paper, we propose an automatic and mechanized license and number plate recognition (LNPR) system which can extract the license plate number of the vehicles passing through a given location using image processing algorithms. No additional devices such as GPS or radio frequency identification (RFID) need to be installed for implementing the proposed system. Using special cameras, the system takes pictures from each passing vehicle and forwards the image to the computer for being processed by the LPR software. Plate recognition software uses different algorithms such as localization, orientation, normalization, segmentation and finally optical character recognition (OCR). The resulting data is applied to compare with the records on a database. Experimental results reveal that the presented system successfully detects and recognizes the vehicle number plate on real images. This system can also be used for security and traffic control.

(Keywords— License and number plate recognition (LNPR) system, image processing, orientation, normalization, segmentation, identification, optical character recognition (OCR

فایل PDF – در 5 صفحه- نویسنده : Hamed Saghaei

Proposal for Automatic License and Number Plate

پسورد فایل : behsanandish.com


LICENSE PLATE MATCHING TECHNIQUES

تکنیک های انطباق پلاک وسیله نقلیه

فایل PDF – در 42 صفحه- نویسنده : U.S.Department of Transportation-Federal Highway Administration(وزارت راه و ترابری آمریکا-مدیریت بزرگراه فدرال)

LICENSE PLATE MATCHING TECHNIQUES

پسورد فایل : behsanandish.com


Development of a New Automatic License Plate Recognition (LPR) System

توسعه یک سیستم تشخیص پلاک خودکار جدید

ABSTRACT In Japan, automatic license plate recognition systems have been used for more than ten years for the purposes of measuring the travel time of vehicles and for some applications which need detailed plate information identification. Due to their efficacy, they are now being utilized throughout the country. Ordinarily, compared to when used for travel time measurements, considering the types of uses for the number information, higher recognition accuracy is often desired when used for some applications which need detailed plate information identification. We have advanced the development of number plate reading for the purpose of travel time measurement applications, refining these technologies for their application to other various applications. In order to fulfill the requirements expected to be met for various applications, we have implemented a variety of innovations in both software and hardware and developed a new LPR system that has many features such as high recognition rate, low false rate, compact design and high reliability by image processing algorithms and an advanced camera unit. We will seek to expand abroad by applying these technologies.

KEYWORDS: Automatic license plate recognition, Automatic number plate recognition, Automatic vehicle identification, Image processing, Vehicle detection, Plate extraction, Character recognition

فایل PDF – در 10 صفحه- نویسنده : Takehiko Kato ,Masatoshi Asada , Kayo Tanaka , Yusuke Yasuhara, Toshihiro Asai , Yasuo Ogiuchi

Development of a New Automatic License Plate Recognition (LPR) System

پسورد فایل : behsanandish.com


Development of a License Plate Number Recognition System Incorporating LowResolution Cameras

توسعه یک سیستم شناسایی شماره پلاک شامل دوربین های با رزولوشن پایین

A multi-lane free flow (MLFF) toll collection system installed on a simplified gantry requires compact cameras for supervising enforcement. Because these compact cameras have low image resolution, it is also necessary to develop vehicle license plate recognition technology that uses dynamic image processing. Mitsubishi Heavy Industries, Ltd. (MHI) has developed three technologies based on the conventional license plate recognition system using still images; these technologies improve image quality, process plural images of a single vehicle, and utilize a reference database. Laboratory evaluation tests have verified that even a lowresolution camera system can successfully recognize license plate numbers at a rate of 95% or better, comparable to results from the conventional still image system. MHI is enhancing system robustness to enable application of these technologies to actual products.

فایل PDF – در 5 صفحه- نویسنده : KENTA NAKAO, KIICHI SUGIMOTO, MAYUMI SAITOH, TAKUMA OKAZAKI

Development of a License

پسورد فایل : behsanandish.com


Automatic Number Plate Recognition System

سیستم شناسایی شماره پلاک خودکار

Abstract. Automatic recognition of car license plate number became a very important in our daily life because of the unlimited increase of cars and transportation systems which make it impossible to be fully managed and monitored by humans, examples are so many like traffic monitoring, tracking stolen cars, managing parking toll, red-light violation enforcement, border and customs checkpoints. Yet it’s a very challenging problem, due to the diversity of plate formats, different scales, rotations and non-uniform illumination conditions during image acquisition. This paper mainly introduces an Automatic Number Plate Recognition System (ANPR) using Morphological operations, Histogram manipulation and Edge detection Techniques for plate localization and characters segmentation. Artificial Neural Networks are used for character classification and recognition.
2010 Mathematics Subject Classification. Primary 68T10; Secondary 68T45.

Key words and phrases. license plate recognition, plate region extraction, segmentation, neural networks, optical character recognition, Hough transform, ANPR.

فایل PDF – در 10 صفحه- نویسنده :Amr Badr, Mohamed M. Abdelwahab, Ahmed M. Thabet, and Ahmed M. Abdelsadek

Automatic Number Plate Recognition System

پسورد فایل : behsanandish.com


Automatic License Plate Recognition

شناسایی شماره پلاک خودکار

فایل PDF – در 5 صفحه- نویسنده :Jason Grant

Automatic License Plate Recognition

پسورد فایل : behsanandish.com


A Real-Time Mobile Vehicle License Plate Detection and Recognition

یک تشخیص و ردیابی شماره پلاک وسایل نقلیه موبایل زمان واقعی

Abstract
In this paper we present a instant and real-time mobile vehicle license plate recognition system in an open environment. Using a nonfixed video camera installed in the car, the system tries to capture the image of the car in front and to process instant vehicle license plate detection and recognition. We utilize the color characteristics of the barking lights to carry out license plate detection. We first detect the location of the two barking lights in the captured image. Then set license plate detection region using the probability distribution of the license plate between the two lights. This method can eliminate any environmental interference during the license plate detection and improve the rate of accuracy of license plate detection and recognition. Moreover, we use the morphology method Black Top-Hat to enhance the level of separation of the license plate characters. Experiments show that the system can effectively and quickly capture the vehicle image,detect and recognize the license plate whether it is in daytime, nighttime, clear day, raining day or under complicated environment.
Key Words: Real-Time, Wavelet, License Plate, Black Top-Hat

فایل PDF – در 10 صفحه- نویسنده :Kuo-Ming Hung and Ching-Tang Hsieh

A Real-Time Mobile Vehicle License Plate

پسورد فایل : behsanandish.com