현실감각 0% :: '컴퓨터 관련' 카테고리의 글 목록 (6 Page)

컴퓨터 관련 2011. 12. 5. 10:16

인공신경망(Neural Network) c# 코딩



요즘 인공신경망이 갑자기 필요한데 개발 플랫폼인 C#으로 코딩해놓은것이 없어서 예전 매트랩 소스보면서 다시 코딩..


위 화면은 시작하면 나오는 화면..;; 테스트 해봐야 하는데 아직 특별한 데이터가 없어서 색상과 당도, 산도를 이용하여 과일과 채소를 구분하는 프로그램(?) 작성ㅋㅋ;

좌측 학습 영역에 객체의 특징데이터를 입력하고 종류를 결정한 후 학습을 누르면 자동 학습된다.

특징 데이터 입력은 0~1 사이의 소수를 입력받는다... 사과를 예로 들면





0부터 255 사이의 값을 갖는 RGB 값이 208, 175, 106으로 나왔다. 이것을 0~1 사이의 값으로 정규화하면..
0.8156, 0.6862, 0.4156 의 값으로 변환 가능하다.
이것들을 각각 RED, GREEN, BLUE 칸에 입력하고,
당도와 산도는... 설탕의 당도를 1로 잡고, 식초의 산도를 1로 잡았을때 비교해서
대충 사과는 많이 달고 약간 시큼하니까 0.7, 0.5정도로 넣었다...-_-;;

그 다음에.. 종류에는 과일일 경우는 1, 채소일 경우에는 0을 넣자.
(반대로 해도 상관은 없다; 알아볼수만 있다면;;)

이런식으로 특징값을 수치화하여 각각의 학습 데이터들을 입력한 후, 아래의 학습 버튼을 누르면 자동으로 학습되며, 그 가중치 값은 프로그램이 설치된 폴더의 u.txt, v.txt에 각각 저장된다.





u.txt와 v.txt가 제대로 생성되었다면 학습 성공!!

학습이 끝났다면 이제부터 인식이 가능하다. 오른쪽 메뉴의 인식 영역에서 아무값이나(그래도 0부터 1사이의 소수만 가능;; 아무값이나 입력했다가 문제생겨도 책임안짐;;) 입력하고 인식을 눌러보자.
입력된 특징값을 바탕으로 과일인지 채소인지를 구분하여 출력할 것이다.
결과값이 1에 가까우면 과일, 0에 가까우면 채소가 되겠다~




코드는 여기~!


질문은 메일로~!
chabert1@nate.com


 

 


컴퓨터 관련 2011. 11. 10. 14:17

[C#, openCVSharp] SURF를 이용한 PCB 쇼트-서킷(short circuit) 검출




저번 포스팅에 썼던 SURF를 이용하여 수작업으로 조립하는 사이드키 납땜부분의 쇼트-서킷(이하 쇼트) 검출 프로그램 개발!





순서는...

일단 입력영상을 SURF를 이용하여 원근변환(Perspective Transform) 적용 후





검출영역을 ROI로 설정하고, Otsu 알고리즘으로 이진화 한 후에 레이블링해서 레이블 개수로 판별-_-;
뭐 아직 연구개발 초창기니까-_-;;;;;;

 


이놈은 쇼트 난 영상 결과. 맨 아래 깔끔한 영상은 비교영상이다.



이녀석은 양품


귀찮아서 대충 레이블링으로 쇼트 여부를 검출하였지만, 모폴로지 연산과 컨투어, 컨벡스헐 등을 잘 조합하면 훨씬 좋은(그래봤자 openCV에서 전부 제공하는 기본 영상처리지만...ㅋㅋㅋㅋ) 성능을 보일것으로 판단된다.

최신 논문들도 좀 보고 계속 공부해야하는데 단순한 영상처리 소스 몇개 조합해서 하루하루 대충 수습하는 중..ㅠㅠ 과장님 죄송합니다.ㅠㅠ SQMS도 해야하고, 자재관리하는 프로그램도 만들어야하고, 인사관리시스템 급여부분도 만들어야하고, 각종 버그도 수정해야하고... 시간이 없어요.ㅠㅠ흑흐그흐그그휴ㅜㅠ

소스는 저번 포스팅에 있는 SURF 소스에 ROI 설정부분과 레이블링 소스만 추가(-_-;;)



컴퓨터 관련 2011. 10. 14. 19:53

[C#, openCVSharp] 회전된 PCB 불량탐지를 위한 SURF




요즘 갑작스레 PCB 기판 불량 탐지하는 프로젝트를 한다고 해서 이것저것 준비중인데, 그 중 하나가 바로 컨베이어벨트에 아무렇게나 던져져있는 기판의 불량을 찾는 것이란다...킁;
일반적으로 2D 불량탐지는 차연산을 통해 하기 때문에 비교영상과의 정확한 매칭이 필수인데, 아무렇게나 던져진 오브젝트라니....ㅠㅠ

일단 연구계획관련 문서를 만들기 위해 회전된 오브젝트를 어떻게 바로 세울까 고민하다가 귀차니즘이 발동하여 SURF로 특징 잡고, 특징을 기반으로 회전시키는 방법을 사용하기로 했다.
물론 이 방법은 좀 느리다보니(내 데스크탑으로 약 1초 소요) 어디까지나 '이러이러한 기술을 보유하고 있다' 하고 가라로 문서 작성할때나 사용할 것이고, 연구일정이 잡히면 더 좋은 방법을 생각해 봐야겠다.ㅠ

개발 언어는 C#, 라이브러리는 openCVSharp을 사용했고, 뭐 알만한 사람은 소스만 봐도 아시겠지만
opencvsharp 홈페이지(https://code.google.com/p/opencvsharp/) 예제를 그대로 가져다 썼다.ㅋㅋ
그래도 회전시키는 소스 (//////////으로 주석처리된 부분)는 직접 추가... -_-;

아래는 과정과 결과 사진

그림 1. 미리 찍어둔 비교하고자 하는 사진

그림 2. 촬영한 오브젝트 사진


그림 3. SURF 로 영상 비교


그림 4. 비교사진(그림1)의 각도와 위치에 맞게 Perspective Transform한 오브젝트 사진(그림2)


아래는 소스.
(뭐.. 내가 짠 소스도 아니고... 추가한 부분은 회전을 위해 Perspective Transform 한 것밖에..
이마저도 openCVSharp 예제소스 퍼와서 사용 ㅋㅋㅋㅠㅠㅠ 아 이러다 가뜩이나 구질구질한 코딩실력 나락으로 빠질듯ㅋㅋ)

public SURFSample()
        {
            IplImage objx = Cv.LoadImage("pcb.jpg");
            IplImage obj = Cv.CreateImage(objx.Size, BitDepth.U8, 1);
            IplImage image = Cv.CreateImage(objx.Size, BitDepth.U8, 1);
            IplImage dst = Cv.CreateImage(objx.Size, BitDepth.U8, 1);
            Cv.Copy(obj, dst);
            Cv.CvtColor(objx, obj, ColorConversion.BgrToGray);
            using (CvCapture cap = CvCapture.FromCamera(0))
            using (CvWindow w = new CvWindow("Processing Image"))
            using (CvWindow m = new CvWindow("Result Image"))
            {
                while (CvWindow.WaitKey(10) < 0)
                {
                    using (IplImage imagex = cap.QueryFrame())
                        Cv.CvtColor(imagex, image, ColorConversion.BgrToGray);
                    using (CvMemStorage storage = Cv.CreateMemStorage(0))
                    using (IplImage objColor = Cv.CreateImage(obj.Size, BitDepth.U8, 3))
                    using (IplImage correspond = Cv.CreateImage(new CvSize(image.Width, obj.Height + image.Height), BitDepth.U8, 1))
                    {

                        Cv.CvtColor(obj, objColor, ColorConversion.GrayToBgr);

                        Cv.SetImageROI(correspond, new CvRect(0, 0, obj.Width, obj.Height));
                        Cv.Copy(obj, correspond);
                        Cv.SetImageROI(correspond, new CvRect(0, obj.Height, correspond.Width, correspond.Height));
                        Cv.Copy(image, correspond);
                        Cv.ResetImageROI(correspond);

                        CvSeq<CvSURFPoint> objectKeypoints, imageKeypoints;
                        CvSeq<float> objectDescriptors, imageDescriptors;
                        Stopwatch watch = Stopwatch.StartNew();
                        {
                            CvSURFParams param = new CvSURFParams(500, true);
                            Cv.ExtractSURF(obj, null, out objectKeypoints, out objectDescriptors, storage, param);
                            Console.WriteLine("Object Descriptors: {0}", objectDescriptors.Total);
                            Cv.ExtractSURF(image, null, out imageKeypoints, out imageDescriptors, storage, param);
                            Console.WriteLine("Image Descriptors: {0}", imageDescriptors.Total);
                        }
                        watch.Stop();
                        Console.WriteLine("Extraction time = {0}ms", watch.ElapsedMilliseconds);
                        watch.Reset();
                        watch.Start();

                        CvPoint[] srcCorners = new CvPoint[4]{
                            new CvPoint(0,0), new CvPoint(obj.Width,0), new CvPoint(obj.Width, obj.Height), new CvPoint(0, obj.Height)
                        };
                        CvPoint[] dstCorners = LocatePlanarObject(objectKeypoints, objectDescriptors, imageKeypoints, imageDescriptors, srcCorners);


                        if (dstCorners != null)
                        {
                            CvPoint2D32f[] pnt = new CvPoint2D32f[4];
                            double[] dist = new double[4];
                            for (int i = 0; i < 4; i++)
                            {
                                CvPoint r1 = dstCorners[i % 4];
                                CvPoint r2 = dstCorners[(i + 1) % 4];
                                Cv.Line(correspond, new CvPoint(r1.X, r1.Y + obj.Height), new CvPoint(r2.X, r2.Y + obj.Height), CvColor.Black);
                                dist[i] = Math.Sqrt(((r1.X - r2.X) * (r1.X - r2.X)) + ((r1.Y - r2.Y) * (r1.Y - r2.Y)));
                                if (i == 0)
                                {
                                    pnt[0] = new CvPoint2D32f(Convert.ToDouble(r1.X), Convert.ToDouble(r1.Y));
                                    pnt[1] = new CvPoint2D32f(Convert.ToDouble(r2.X), Convert.ToDouble(r2.Y));
                                }
                                else if (i == 2)
                                {
                                    pnt[3] = new CvPoint2D32f(Convert.ToDouble(r1.X), Convert.ToDouble(r1.Y));
                                    pnt[2] = new CvPoint2D32f(Convert.ToDouble(r2.X), Convert.ToDouble(r2.Y));
                                }
                            }
                            ///////////////////////////////
                            CvPoint2D32f[] dstPnt = new CvPoint2D32f[4];
                            dstPnt[0] = new CvPoint2D32f(0.0f, 0.0f);
                            dstPnt[1] = new CvPoint2D32f(639.0f, 0.0f);
                            dstPnt[2] = new CvPoint2D32f(0.0f, 479.0f);
                            dstPnt[3] = new CvPoint2D32f(639.0f, 479.0f);
                            using (CvMat mapMatrix = Cv.GetPerspectiveTransform(pnt, dstPnt))
                            {
                                Cv.WarpPerspective(image, dst, mapMatrix, Interpolation.Linear | Interpolation.FillOutliers, CvScalar.ScalarAll(100));
                            }
                            ///////////////////////////////

                        }

                        int[] ptpairs = FindPairs(objectKeypoints, objectDescriptors, imageKeypoints, imageDescriptors);
                        for (int i = 0; i < ptpairs.Length; i += 2)
                        {
                            CvSURFPoint r1 = Cv.GetSeqElem<CvSURFPoint>(objectKeypoints, ptpairs[i]).Value;
                            CvSURFPoint r2 = Cv.GetSeqElem<CvSURFPoint>(imageKeypoints, ptpairs[i + 1]).Value;
                            Cv.Line(correspond, r1.Pt, new CvPoint(Cv.Round(r2.Pt.X), Cv.Round(r2.Pt.Y + obj.Height)), CvColor.White);
                        }

                        //for (int i = 0; i < objectKeypoints.Total; i++)
                        //{
                        //    CvSURFPoint r = Cv.GetSeqElem<CvSURFPoint>(objectKeypoints, i).Value;
                        //    CvPoint center = new CvPoint(Cv.Round(r.Pt.X), Cv.Round(r.Pt.Y));
                        //    int radius = Cv.Round(r.Size * (1.2 / 9.0) * 2);
                        //    Cv.Circle(objColor, center, radius, CvColor.Red, 1, LineType.AntiAlias, 0);
                        //}
                        watch.Stop();
                        Console.WriteLine("Drawing time = {0}ms", watch.ElapsedMilliseconds);

                        Cv.NamedWindow("Object", WindowMode.AutoSize);
                        Cv.NamedWindow("Object Correspond", WindowMode.AutoSize);
                        Cv.ShowImage("Object Correspond", correspond);
                        Cv.ShowImage("Result Image", obj);
                        Cv.ShowImage("Processing Image", image);
                        Cv.ShowImage("Object", dst);

                        Cv.WaitKey(0);

                        Cv.DestroyWindow("Object");
                        Cv.DestroyWindow("Object Correspond");
                    }
                }
            }
        }