크롬은 컨텍스트 메뉴를 통해서 손쉽게 웹 페이지를 디버깅할 수 있는 방법(요소 검사)을 제공하고 있습니다. 개인적으로 자주 그리고 유용하게 사용하는 기능이라서 사파리에서도 동일한 인터렉션으로 디버깅 툴을 사용할 수 있을 것이라고 기대했는데 다음과 같은 개발자 옵션을 선택해야만 디버깅 툴을 사용할 수 있습니다. 


"환경 설정 > 고급 > 메뉴 막대에 개발자용 메뉴 보기"


크롬에 너무 길들어져 있었던 탓인지 아래 웹 사이트를 찾는 동안 툴툴거렸습니다. :P 



Posted by 완소타코

댓글을 달아 주세요

시간이 지난 소식이기는 한데 Qt가 Nokia의 품에서 떠나 Digia에 매각됐네요. 개인적으로 Nokia가 Qt를 편입하면서 LGPL 라이센스 채택 및 개발자 네트워크 활성화에 많은 노력을 기울였던 부분은 긍정적으로 평가하고 있습니다. 다만 Nokia의 모바일 시장에서의 참패 탓에 Qt의 미래까지 불투명해진 사실이 못내 아쉬웠는데 이런 일이 있었군요. Qt가 Digia의 품에서 다시 도약할 수 있는 계기를 마련했으면 좋겠습니다.

Posted by 완소타코
TAG Diigia, qt

댓글을 달아 주세요

이번에는 OpenCV의 마법같은 매력을 체험할 수 있는 예제를 만들었습니다. 이름하여 템플릿 매칭입니다. 원본 이미지에서 템플릿으로 주어진 이미지에 해당 되는 영역을 찾는 기술입니다. 과학수사물에 빠짐없이 나오는 장면 중 하나가 컴퓨터를 이용해서 용의자의 얼굴을 대조하거나 일치하는 지문을 찾는 모습인데요. 저는 템플릿 매칭이라는 기술을 살펴보면서 그 장면이 제일 먼저 떠올랐습니다. :)

재미있는 샘플 이미지가 없을까 고민하다가 구글 이미지 검색에서 심슨 이미지를 발견했습니다.



위 이미지에서 밀하우스를 찾아볼 예정입니다. 이 친구가 바로 밀하우스입니다.



그럼 밀하우스를 찾는 소스 코드를 살펴볼까요?


#!/usr/bin/env python
# -*- coding: utf-8 -*-

from opencv.cv import *
from opencv.highgui import *
from opencv import *

if __name__ == '__main__':
     source = cvLoadImage('simpson.jpg')
     template = cvLoadImage('milhouse.jpg')

     width = source.width - template.width + 1
     height = source.height - template.height + 1
     result = cvCreateImage(cvSize(width, height), 32, 1)

     mathod = CV_TM_SQDIFF
     #mathod = CV_TM_SQDIFF_NORMED
     #mathod = CV_TM_CCORR
     #mathod = CV_TM_CCORR_NORMED
     #mathod = CV_TM_CCOEFF
     #mathod = CV_TM_CCOEFF_NORMED
     cvMatchTemplate(source, template, result, mathod)

     minval, maxval, minloc, maxloc = cvMinMaxLoc(result, 0)
    
     matchloc = cvPoint(0, 0)
     if mathod == CV_TM_SQDIFF or mathod == CV_TM_SQDIFF_NORMED:
          matchloc = minloc
     else:
          matchloc = maxloc

     cvRectangle(source, cvPoint(matchloc.x, matchloc.y), cvPoint(matchloc.x + template.width, matchloc.y + template.height), CV_RGB(255, 0, 0))

     cvNamedWindow('Source', CV_WINDOW_AUTOSIZE)
     cvNamedWindow('Result', CV_WINDOW_AUTOSIZE)    

     cvShowImage('Source', source)
     cvShowImage('Result', result)

     cvWaitKey(0)

     cvReleaseImage(source)
     cvReleaseImage(template)
     cvReleaseImage(result)

     cvDestroyWindow('Source')
     cvDestroyWindow('Result')

22번 ~ 32번 라인이 실제 템플릿 매칭을 수행하고, 입력으로 주어진 이미지와 유사한 영역을 표시하는 부분입니다. 소스 코드는 생각보다 짧고 간단합니다. 물론 내부적으로는 많은 연산을 수행하겠죠?


22번 라인의 cvMatchTemplate()이 템플릿 매칭을 수행하는 함수입니다. 파라미터로 입력 이미지(심슨 캐릭터들의 이미지), 매칭에 사용할 이미지(밀하우스), 결과 이미지, 매칭 방법을 받습니다. 참고로 결과 이미지의 크기는 아래의 값으로 설정되어야 합니다. (12, 13번 라인 참고)


결과 이미지의 크기 : (W - w + 1) x (H - h + 1)

W: 입력 이미지 Width
H: 입력 이미지 Height
w: 템플릿 이미지 Width
h: 템플릿 이미지 Height


cvMatchTemplate()는 총 6가지의 매칭 방법을 제공합니다. 실제로는 복잡한 수식을 기반으로 동작 하지만 특별한 경우가 아니라면 고려할 필요는 없을 것 같습니다.

  • CV_TM_SQDIFF - 제곱차 매칭
  • CV_TM_SQDIFF_NORMED - 제곱차 매칭의 정규화
  • CV_TM_CCORR - 상관관계 매칭
  • CV_TM_CCORR_NORMED - 상관관계 매칭의 정규화
  • CV_TM_CCOEFF - 상관계수 매칭
  • CV_TM_CCOEFF_NORMED - 상관계수 매칭의 정규화

매칭 방법에 따라서 결과 값이 다르게 나오는데요. 제곱차 매칭은(CV_TM_SQDIFF, CV_TM_SQDIFF_NORMED) 일치할 수록 값이 작게 나오고 일치하지 않으면 값이 크게 나옵니다. 상관관계, 상관계수는 반대로 일치할 수록 높은 값이 일치하지 않을 수록 작은 값이 나옵니다.


24번 라인의 cvMinMaxLoc()을 이용하면 result 이미지에서 최소값과 최대값이 어디에 위치해있는지 알 수 있는데요. 이 영역을 찾아 입력 이미지에 사각형을 그리면(32번 라인) 매칭되는 부분을 나타낼 수 있습니다. 정규화 방법은 입력 이미지와 템플릿 이미지 사이에 조명의 차이가 존재할 때 영향을 줄이기 위한 방법으로 사용된다고 합니다.


아래와 같이 밀하우스를 찾았습니다.


이유는 모르겠지만 CV_CCORR를 사용하면 아래와 같이 엉뚱한 영역을 표시합니다. 저기에는 아무도 없는데 말이죠. :)


정리하면 cvMatchTemplate()은 템플릿 이미지를 왼쪽에서 오른쪽으로, 위에서 아래로 한 픽셀씩 이동하면서 입력 이미지와 비교하고 유사성을 계산해서 그 결과를 반환합니다. 그리고 cvMinMaxLoc()을 이용해 결과 영상에서 최소값 또는 최대값의 좌표를 찾음으로써 템플릿 이미지와 유사한 영역을 찾아낼 수 있습니다.


소스 코드는 아래 링크를 통해서도 살펴볼 수 있습니다.



참고 자료




'OpenCV' 카테고리의 다른 글

[OpenCV] Tutorial #3 - 템플릿 매칭  (0) 2012.06.26
[OpenCV] Tutorial#2 - 모자이크 효과 만들기  (0) 2012.06.21
[OpenCV] Tutorial #1 - Hello World  (0) 2012.06.20
Posted by 완소타코

댓글을 달아 주세요

이번 예제는 좀 더 그럴 듯한 결과를 보여주는 소스 코드를 만들어봤습니다. 원본 이미지의 픽셀 정보를 이용해서 모자이크와 비슷한(?) 효과를 내는 예제입니다.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from opencv.cv import *
from opencv.highgui import *
from opencv import *

if __name__ == '__main__':
     image = cvLoadImage('fruits.jpg')
     dotImage = cvCreateImage(cvGetSize(image), image.depth, image.nChannels)

     cvNamedWindow('Mosaic Source', CV_WINDOW_AUTOSIZE)
     cvNamedWindow('Mosaic Output', CV_WINDOW_AUTOSIZE)

     cvShowImage('Mosaic Source', image)

     tileCols = 64
     tileRows = 60
     tileWidth = image.width / tileCols
     tileHeight = image.height / tileRows

     for y in range(tileRows):
          for x in range(tileCols):
               color = cvGet2D(image, (y * tileHeight) + (tileHeight / 2), (x * tileWidth) + (tileWidth / 2))
               cvRectangle(dotImage, (x * tileWidth, y * tileHeight), (x * tileWidth + tileWidth, y * tileHeight + tileHeight), (0, 0, 0))
               cvRectangle(dotImage, (x * tileWidth + 1, y * tileHeight + 1), (x * tileWidth + tileWidth - 1, y * tileHeight + tileHeight - 1), color, CV_FILLED)
               #cvCircle(dotImage, ((x * tileWidth) + (tileWidth / 2), (y * tileHeight) + (tileHeight / 2)), tileWidth / 2, color, CV_FILLED)

     cvShowImage('Mosaic Output', dotImage)

     cvWaitKey(0)

     cvReleaseImage(image)
     cvReleaseImage(dotImage)
     cvDestroyWindow('Mosaic Source')
     cvDestroyWindow('Mosaic Output')

원본 이미지를 적당한 크기(64x60)의 격자 형태로 이미지를 출력하는 것인데요. 하나의 격자를 구성할 색상 정보를 원본 이미지로부터 얻어온 뒤, 이를 새로운 윈도우에 출력하는 방식을 사용합니다.

24번 라인에서 cvGet2D가 원본 이미지로부터 색상 정보를 가져오는 부분이고, 격자에 해당하는 부분의 가운데 픽셀 값을 가져옵니다. (격자에 해당하는 모든 픽셀의 평균값을 구해도 됩니다) 25, 26번 라인에서 cvRectangle을 이용해서 새로운 윈도우에 격자를 하나씩 그립니다. 두 번의 cvRectangle이 사용된 이유는 단순히 cvRectangle에서 외곽선을 그려 조금 더 미려하게 보이도록 하기 위한 것입니다.

실행 결과는 다음과 같습니다.

원본 



모자이크 효과



소스 코드에서 26번 라인을 주석 처리하고 바로 아래의 cvCircle 부분을 주석 해제하면 아래와 같은 결과를 얻을 수 있습니다. 전광판 느낌도 조금 나는 것 같지 않나요? :)



소스 코드는 아래에서 내려받을 수 있습니다.



'OpenCV' 카테고리의 다른 글

[OpenCV] Tutorial #3 - 템플릿 매칭  (0) 2012.06.26
[OpenCV] Tutorial#2 - 모자이크 효과 만들기  (0) 2012.06.21
[OpenCV] Tutorial #1 - Hello World  (0) 2012.06.20
Posted by 완소타코

댓글을 달아 주세요

OpenCV 파이썬 튜토리얼을 간단하게 만들어봤습니다. 첫번째 예제로 이미지 파일을 화면에 보여주고, 이미지 위에 Hello World를 출력하는 간단한 코드를 소개합니다.


#!/usr/bin/env python
# -*- coding: utf-8 -*-

from opencv.cv import *
from opencv.highgui import *

if __name__ == '__main__':
    image = cvLoadImage('sample.png')
    font = cvInitFont(CV_FONT_HERSHEY_SIMPLEX, 1, 1, 0, 2, 8)
    cvPutText(image, 'Hello World', (20, 40), font, (255, 255, 255))

    cvNamedWindow('Tutorial#1', CV_WINDOW_AUTOSIZE)
    cvShowImage('Tutorial#1', image)

    cvWaitKey(0)

    cvReleaseImage(image)
    cvDestroyWindow('Tutorial#1')
  • cvLoadImage는 이미지 파일을 메모리 공간으로 불러오는 역할을 합니다.
  • cvInitFont는 폰트 객체를 초기화 하는 역할을 합니다. 파라미터 정보는 다음을 참고하세요.
    • InitFont(fontFace, hscale, vscale, shear=0, thickness=1, lineType=8)
      • fontFace (int) - 폰트 타입
      • hscale (float) - 너비 지정
      • vscale (float) - 높이 지정
      • shear (float) - 폰트 기울기
      • thickness (int) - 폰트 선 두께
      • lineType (int) - 폰트 선 타입
  • cvPutText는 이미지 위에 폰트 객체를 이용해서 문자를 출력하는 함수입니다. 위치 및 색상을 설정해서 원하는 위치에 출력할 수 있습니다.
  • cvNamedWindow는 윈도우를 생성합니다.
  • cvShowImage는 윈도우에 이미지를 출력합니다.
  • cvWaitKey는 키 입력을 기다리는 함수입니다.
  • cvReleaseImage는 이미지 객체를 소멸합니다.
  • cvDestoryWindow는 윈도우를 소멸합니다.

실행 결과는 다음과 같습니다. 



OpenCV를 사용하면 짧은 소스 코드로도 이미지와 관련된 많은 처리를 할 수 있습니다. 이미지 버퍼를 내부적으로 생성하고, 이미지 포맷에 대한 처리를 개발자가 고민할 필요가 없다는 것과 폰트 객체를 생성하고, 윈도우를 만드는 것이 모두 한 줄의 코드로 가능하기 때문에 오로지 이미지 처리와 관련된 부분에만 집중할 수 있습니다.


아직은 저도 OpenCV 뉴비이기 때문에 라이브러리의 1%도 체험을 못한 것 같습니다. 계속 공부하면서 OpenCV의 장점을 발견해보겠습니다. :)


소스 코드는 아래에서 내려받을 수 있습니다.



참고 페이지





'OpenCV' 카테고리의 다른 글

[OpenCV] Tutorial #3 - 템플릿 매칭  (0) 2012.06.26
[OpenCV] Tutorial#2 - 모자이크 효과 만들기  (0) 2012.06.21
[OpenCV] Tutorial #1 - Hello World  (0) 2012.06.20
Posted by 완소타코
TAG OpenCV

댓글을 달아 주세요



티스토리 툴바