현실감각 0% :: '분류 전체보기' 카테고리의 글 목록 (13 Page)

컴퓨터 관련 2011. 9. 7. 10:05

Data Matrix 바코드 인식



회사에서 생산하는 PCB를 Data Matrix 형식의 2D 바코드로 관리하고 있는데... 바코드 프린터를 바꿨더니 바코드스캐너가 인식을 못한다. 그래서 3시간 코딩.. 아니 3시간 웹서핑해서 구한 코드를 조합해서 카메라로 바코드 인식하는 프로그램 완성!!




영상처리나 비전 코딩할때는 openCV를 주로 사용해서 C++이 익숙한데, 회사에서 개발할 때는 대부분 C#을 쓰기 때문에 어떻게 할까 고민하며 인터넷 서핑하다가 린토리(http://entist.tistory.com) 님께서 블로그에 올려주신 openCVSharp 프로젝트 파일을 베이스로 사용하였음.
저분 블로그에 openCV를 C#에서 사용하게끔 해주는 openCVSharp 설명과 예제가 잘 나와있어서 openCVSharp 문외한인 내가 헤딩하며 5~7시간 작업할 것을 30분만에 해결!!!

Data Matrix 디코딩 하려고 관련 논문 검색. 막상 몇장 구해놓고 보니 영어의 압박에 눈이 감겨서 그냥 오픈소스가 있나 구글신께 부탁해봄.
하지만 구글신께서 요즘 모토로라 인수하는 바람에 바쁘셨는지, 유료 SDK와 무슨 이상한 토렌트 다운로드 사이트만 알려주심. 그래서 재야 개발자들의 모임 sourceforge에서 다시 검색했더니 c#으로 사용할 수 있는 디코더 발견!!(인코딩도 됨!!)

바로 여기! DataMatrix.Net
http://sourceforge.net/projects/datamatrixnet/

사용법 뭐 그런거 없다.
DataMatrix.net.dll 참조하고 제공하는 함수 가져다 쓰면 됨;
아래는 기본 제공하는 예제소스에 인코딩, 디코딩 섞여있어 디코딩만 쏙 빼낸 소스~

        static void Main(string[] args)
        {
            TestMatrixEnDecoder();
        }

        private static void TestMatrixEnDecoder()
        {
            DmtxImageDecoder decoder = new DmtxImageDecoder();
            List<string> codes = decoder.DecodeImage((Bitmap)Bitmap.FromFile(@"c:\test.png"), 1, new TimeSpan(0, 0, 3));
            foreach (string code in codes)
            {
                Console.WriteLine("Decoded:\n" + code);
            }
        }



TestMatrixEnDecoder();
이 함수 말고도 두개인가(아니면 더 많을지도) 더 제공하는데 써보지는 않았다.
그냥 젤 위에 있어서 선택함.
결과는 초점도 잘 안맞는 2만원짜리 웹캠으로 찍은 결과물도 그럭저럭 데이터가 잘 나왔다.
물론 오인식 하는 경우도 몇번 발생했지만, 뭐 팔아먹을것도 아니고 혼자 쓸건데 이정도면 감지덕지^-^




컴퓨터 관련 2011. 4. 8. 09:08

FFMPEG for Windows DLL



Visual C++에서 ffmpeg를 가져다 쓸 일이 생겼는데 dll 만들기가 귀찮아서 구글링하다가 발견.
ffmpeg 소스를 수정할 일이 있다면 모를까 그냥 쓰는거라면 미리 컴파일된 dll을 가져다 쓰는게 편하니;;

http://ffmpeg.arrozcru.org/builds/


컴퓨터 관련 2011. 3. 29. 11:37

Inverse Polar Transform




요즘 되지도 않을 것 같은 360도 카메라 프로젝트인가 뭔가때문에 골치아프다.
이놈의 주 목적은 사방 360도를 n개의 카메라로 촬영해서 방범용으로 쓴다는 건데...
꼭 n개가 필요할까 싶어 좌우상하 180도 화각을 갖는 어안렌즈 검색하던 도중 이런 영상을 만났다.



 



오~ 카메라 하나로 360도 다 보이기는 하는데.. 눈 건강에 그리 좋을것 같진 않다. 어린왕자의 소혹성 B612도 아니고.. 이게 뭐임;;
이 카메라 만드는 회사에서 소프트웨어를 하나 주길래 다운받아보니 바로 저놈을 평평하게 펴주는 프로그램!!!

그래서...

그 친구들도 만드는데 못만들까 싶어 함 만들어봤다. 평평하게 펴주는 변환!!!
정식명칭은 Inverse Polar Transform
억지로 번역하자면 역 극변환 정도?;;

이것저것 잡다한건 openCV로 처리했다. (잡다할것도 없지만...)

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "cv.h"
#include "cxcore.h"
#include "highgui.h"
#include <math.h>

IplImage* ComputeInversePolarTransformUsingOpenCV(IplImage* srcImg, int srcWidth, int srcHeight, int dstWidth, int dstHeight)
{
 int centerX = srcWidth / 2;
 int centerY = srcHeight / 2;
 double radius = sqrt((double)(centerX - 0) * (double)(centerX - 0) + (double)(centerY - 0) * (double)(centerY - 0));
 double radiusTemp = sqrt((double)(centerX - srcWidth) * (double)(centerX - srcWidth) + (double)(centerY - 0) * (double)(centerY - 0));
 if(radiusTemp > radius)
  radius = radiusTemp;
 radiusTemp = sqrt((double)(centerX - 0) * (double)(centerX - 0) + (double)(centerY - srcHeight) * (double)(centerY - srcHeight));
 if(radiusTemp > radius)
  radius = radiusTemp;
 radiusTemp = sqrt((double)(centerX - srcWidth) * (double)(centerX - srcWidth) + (double)(centerY - srcHeight) * (double)(centerY - srcHeight));
 if (radiusTemp > radius)
  radius = radiusTemp;
 int radiusInt = (int)radius;
 if(dstWidth < 0)
  dstWidth = radiusInt;
 
 CvSize dstSize;
 dstSize.width = dstWidth;
 dstSize.height = dstHeight;
 IplImage* dstImg = cvCreateImage(dstSize, IPL_DEPTH_8U, 3);
 
 for(int yy = 0; yy < dstHeight; yy++)
 {
  for(int xx = 0; xx < dstWidth; xx++)
  {
   double r = xx;
   double angle = (yy / (double)dstHeight) * CV_PI * 2;

   double y = (r * cos(angle)) + centerX;
   double x = abs((r * sin(angle)) + centerY);
   
   if((yy < 0 || xx < 0 || yy >= dstHeight || xx >= dstWidth) || (int)y < 0 || (int)x < 0 || (int)y >= srcHeight || (int)x >= srcWidth)
   {}
   else
   {
    dstImg->imageData[(yy * dstWidth + xx) * 3] = srcImg->imageData[((int)y * srcWidth + (int)x) * 3];
    dstImg->imageData[(yy * dstWidth + xx) * 3 + 1] = srcImg->imageData[((int)y * srcWidth + (int)x) * 3 + 1];
    dstImg->imageData[(yy * dstWidth + xx) * 3 + 2] = srcImg->imageData[((int)y * srcWidth + (int)x) * 3 + 2];
   }
  }
 }
 //cvNamedWindow("Test", CV_WINDOW_AUTOSIZE);
 //cvShowImage("Test", dstImg);
 //cvWaitKey(0);

 return dstImg;
}


우선... 매개변수로 입력영상, 입력영상의 가로세로 길이, 그리고 출력영상의 가로세로 길이를 받는다.
그담엔... 중점을 구하고... (정사각형이라고 가정하면 꼭 x, y 다받을 필요는 없다)
그담엔 반지름을 구하고...(물론 정사각형이라면 위 코드처럼 복잡하게 쓸 필요 없이 더 간단하게...)
IplImage 부분은 출력영상 생성하는 부분이니까 그냥 뛰어넘고...
앵글 구해준 다음에 입력영상부의 x, y 픽셀 데이터를 앵글을 이용해 새로 생성한 출력영상의 x, y 픽셀에 복사
마지막으로 출력영상 리턴해주면 끝.

출력영상의 너비를 모르기 때문에 출력 영상을 매개변수로 안받고 리턴 처리했다.
(물론 출력영상의 너비를 입력할 수 있지만, 0보다 작은 값을 넣으면 알아서 계산하게끔 했다.)

Interpolation.. 뭐 그런건 귀찮아서 안함-_-;;;
회전도 귀찮아서 안함-_-;;

아래는 결과 영상(회전은 알씨로...-_-;;)




깜장부분 있으면 지저분하니까 크롭!!


당연한 얘기겠지만... 하늘을 바라보고 찍은 사진도 가능하다.(위 사진은 지면을 바라보고 찍은 것)


영상 변환 시 중점에 가까울수록 별로 있지도 않은 픽셀을 억지로 늘리다보니 왜곡이 생긴다.
좌측의 첨탑 꼭대기가 살짝 휜 왜곡은 촬영시의 실제 중심과 영상의 중심이 조금 어긋나서 생긴듯 하다.


참고문헌

http://www.cs.columbia.edu/CAVE/ (영문)
http://en.wikipedia.org/wiki/Polar_coordinate_system (영문-_-;;)