Programming/openCV2024. 2. 24. 23:00

얼마전 테스트 해본 계산 알고리즘은 BM(block match)인데 먼가 먼 곳은 전혀 안 잡아줘서

어떻게 설정을 해야 하나 패러미터를 찾아보고 있었는데 다른 알고리즘이 있다는걸 발견함.

 

 

numDisparities는 검색할 범위. 16의 배수로 하라는데, 해보면 화면의 왼쪽이 사라진다. 지정된 숫자만큼 가장 왼쪽은 버려지는 듯

blockSize. 동일한 블록으로 연산할 단위라고 해야하나. 해당 숫자가 NxN으로 되는건지 숫자가 커지면 블럭이 거칠어 지는 느낌.

numDisparities
the disparity search range. For each pixel algorithm will find the best disparity from 0 (default minimum disparity) to numDisparities. The search range can then be shifted by changing the minimum disparity.

blockSize
the linear size of the blocks compared by the algorithm. The size should be odd (as the block is centered at the current pixel). Larger block size implies smoother, though less accurate disparity map. Smaller block size gives more detailed disparity map, but there is higher chance for algorithm to find a wrong correspondence.

[링크 : https://docs.opencv.org/4.x/d9/dba/classcv_1_1StereoBM.html]

[링크 : https://makepluscode.tistory.com/108]

 

BM 방법은 실내에서나 쓰는거지 실외에서는 잘 안 맞다고 그러니 SGM 기반으로 된 걸 써라~ 인가.

Wrong method. BM is only meant for simple indoor use with low dynamic measuring range. With indoor image, you just need a adjsut mindisp and number of disp and window size.

For outdoor, it is more complex. Maybe u just start. BM and other global based method has the poor result. Either disfigured for overfitting, or streaking effect due to local similarity error.

Current state of the art for traditional CV is the SGM based method proposed by HH. And for the deep learning-based method, there is no best case, vary from case to case/dataset to dataset. The work from lecun Žbontar "Stereo Matching by Training a Convolutional Neural Network " is sth that I used for comparison often.

[링크 : https://stackoverflow.com/questions/62461799/]

 

별별 희한한 알고리즘이 나온다. SGBM? BM 이 붙긴한데..

            alg = strcmp(_alg, "bm") == 0 ? STEREO_BM :
                  strcmp(_alg, "sgbm") == 0 ? STEREO_SGBM :
                  strcmp(_alg, "hh") == 0 ? STEREO_HH :
                  strcmp(_alg, "var") == 0 ? STEREO_VAR : -1;

[링크 : https://copyprogramming.com/howto/opencv-stereo-matching]

 

[링크 : https://docs.opencv.org/4.9.0/d9/dba/classcv_1_1StereoBM.html]

[링크 : https://docs.opencv.org/4.9.0/d2/d85/classcv_1_1StereoSGBM.html]

 

 

SGBM

semi-global block matching algorithm

[링크 : https://amroamroamro.github.io/mexopencv/matlab/cv.StereoSGBM.html]

 

+

2024.02.26

요 근래 버전이긴 한데 오래된 버전에서도 나오긴 하고 python엣도 SGBM이 있으니, 테스트는 해봐야 할 듯.

>>> import cv2>>> cv2.stereo
cv2.stereo                         cv2.stereoRectifyUncalibrated(
cv2.stereoCalibrate(               cv2.stereo_MatchQuasiDense(
cv2.stereoCalibrateExtended(       cv2.stereo_PropagationParameters(
cv2.stereoRectify(                 cv2.stereo_QuasiDenseStereo(

>>> cv2.St
cv2.StereoBM(
cv2.StereoBM_PREFILTER_NORMALIZED_RESPONSE
cv2.StereoBM_PREFILTER_XSOBEL
cv2.StereoBM_create(
cv2.StereoMatcher(
cv2.StereoMatcher_DISP_SCALE
cv2.StereoMatcher_DISP_SHIFT
cv2.StereoSGBM(
cv2.StereoSGBM_MODE_HH
cv2.StereoSGBM_MODE_HH4
cv2.StereoSGBM_MODE_SGBM
cv2.StereoSGBM_MODE_SGBM_3WAY
cv2.StereoSGBM_create(
cv2.Stitcher(
cv2.Stitcher_ERR_CAMERA_PARAMS_ADJUST_FAIL
cv2.Stitcher_ERR_HOMOGRAPHY_EST_FAIL
cv2.Stitcher_ERR_NEED_MORE_IMGS
cv2.Stitcher_OK
cv2.Stitcher_PANORAMA
cv2.Stitcher_SCANS
cv2.Stitcher_create(

 

The definitions of all the arguments are given at the bottom of the documentation page here
In block matching or cv2.StereoBM_create() the disparity is computed by comparing the sum of absolute differences (SAD) of each 'block' of pixels. In semi-global block matching or cv2.StereoSGBM_create() forces similar disparity on neighbouring blocks. This creates a more complete disparity map but is more computationally expensive.
Paper that discusses 'block matching'
Paper that discusses 'semi-global block matching'

[링크 : https://stackoverflow.com/questions/51758076/]

Posted by 구차니

matplotlib을 이용하여 lena를 3d로 그리는게 보이길래 해보려는데

아래와 같이 deprecated 경고만 발생해서 되는걸 못 찾다가

>>> ax = fig.gca(projection='3d')
<stdin>:1: MatplotlibDeprecationWarning: Calling gca() with keyword arguments was deprecated in Matplotlib 3.4. Starting two minor releases later, gca() will take no keyword arguments. The gca() function should only be used to get the current axes, or if no axes exist, create new axes with default keyword arguments. To create a new axes with non-default arguments, use plt.axes() or plt.subplot().

>>> ax= Axes3D(fig)
<stdin>:1: MatplotlibDeprecationWarning: Axes3D(fig) adding itself to the figure is deprecated since 3.4. Pass the keyword argument auto_add_to_figure=False and use fig.add_axes(ax) to suppress this warning. The default value of auto_add_to_figure will change to False in mpl3.5 and True values will no longer work in 3.6.  This is consistent with other Axes classes.

 

chatGPT에게 물어보니 아래와 같이 줘서 시도하니 나오긴 나온다.

import cv2
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# 이미지 읽기
image_path = 't.png'
img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)

# 이미지의 높이와 너비 얻기
height, width = img.shape

# 2D 배열을 생성하여 각 픽셀의 깊이 값을 저장
depth_map = np.zeros_like(img, dtype=np.float32)

# 각 픽셀의 깊이 계산 (여기서는 그레이스케일 값으로 대체)
depth_map = img.astype(np.float32)

# 3D 그래프 생성
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

# X, Y 좌표 생성
x = np.arange(0, width, 1)
y = np.arange(0, height, 1)
x, y = np.meshgrid(x, y)

# 깊이 맵을 사용하여 Z 좌표 생성
z = depth_map

# 3D 그래프에 표시
ax.plot_surface(x, y, z, cmap='viridis')

# 그래프 표시
plt.show()

 

분위기를 보아하니 viridis 를 해서 저런 녹색톤이 나오는것 같은데 plasms가 웬지 flir에서 보던 느런 느낌이려나?

[링크 : https://matplotlib.org/stable/users/explain/colors/colormaps.html]

 

 

위에서 보면 아래와 같이 lena 이미지가 똭!

[링크 : https://stackoverflow.com/questions/31805560/how-to-create-surface-plot-from-greyscale-image-with-matplotlib]

[링크 : https://jehyunlee.github.io/2021/07/10/Python-DS-80-mpl3d2/]

 

 

'Programming > python(파이썬)' 카테고리의 다른 글

pip 패키지 관리  (0) 2024.02.27
pyhthon numpy 생략없이 출력  (0) 2024.02.26
python tcp 서버 예제  (0) 2024.01.22
파이썬 소켓 예제  (0) 2024.01.17
ipython notebook -> jupyter notebook  (0) 2024.01.11
Posted by 구차니
Programming/openCV2024. 2. 21. 23:52

이미지는 아래 github에서 받으면 될 듯.

[링크 : https://github.com/canberkgurel/DisparityMapfromStereoPair]

 

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
imgL = cv.imread('my_photo-1.jpg', cv.IMREAD_GRAYSCALE)
imgR = cv.imread('my_photo-2.jpg', cv.IMREAD_GRAYSCALE)
stereo = cv.StereoBM_create(numDisparities=16, blockSize=5)
disparity = stereo.compute(imgL,imgR)
plt.imshow(disparity,'gray')
plt.show()

[링크 : https://docs.opencv.org/3.4/dd/d53/tutorial_py_depthmap.html]

 

blockSize는 홀수여야 한다고 한다

[링크 : https://makepluscode.tistory.com/108]

 

웹캠을 조금 옆으로 보내 찍고 대충 먼가 인식 가능하게 숫자 적절하게 맞춰서 해보았는데

안경만 도드라지는 느낌..

왼쪽은 16에 5

오른쪽은 16과 7로 설정. 

+

2024.02.23

 

아래 이미지를 이용해서 3d 계산하고

[링크 : https://github.com/canberkgurel/DisparityMapfromStereoPair]

 

나온 depth map을 저장하고

 

depth 맵을 3d 이미지로 변환하면

멀 잘못 만들어 줬는지 z 축과 x 축이 뒤바뀡 모양

아무튼 두상과 램프 스탠드가 깊이로 인식된 것이 보인다.

 

Posted by 구차니
Programming/openCV2024. 2. 20. 19:07

스테레오 카메라를 이용해서 깊이 분석을 하기 전에 렌즈 왜곡을 먼저 잡아야 한다고 한다.

[링크 : https://makepluscode.tistory.com/110]

[링크 : http://www.gisdeveloper.co.kr/?p=6955]

 

 

캘리브레이션은 체커보드 있으면 된다는데, 어찌어찌 만들어 놓았으니 해봐야지

[링크 : https://foss4g.tistory.com/1665]

 

Calibration
Now that we have our object points and image points, we are ready to go for calibration. We can use the function, cv.calibrateCamera() which returns the camera matrix, distortion coefficients, rotation and translation vectors etc.

ret, mtx, dist, rvecs, tvecs = cv.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)

Undistortion
Now, we can take an image and undistort it. OpenCV comes with two methods for doing this. However first, we can refine the camera matrix based on a free scaling parameter using cv.getOptimalNewCameraMatrix(). If the scaling parameter alpha=0, it returns undistorted image with minimum unwanted pixels. So it may even remove some pixels at image corners. If alpha=1, all pixels are retained with some extra black images. This function also returns an image ROI which can be used to crop the result.

So, we take a new image (left12.jpg in this case. That is the first image in this chapter)

img = cv.imread('left12.jpg')
h,  w = img.shape[:2]
newcameramtxroi = cv.getOptimalNewCameraMatrix(mtx, dist, (w,h), 1, (w,h))
1. Using cv.undistort()
This is the easiest way. Just call the function and use ROI obtained above to crop the result.

# undistort
dst = cv.undistort(img, mtx, dist, None, newcameramtx)
# crop the image
x, y, w, h = roi
dst = dst[y:y+h, x:x+w]
cv.imwrite('calibresult.png', dst)

2. Using remapping
This way is a little bit more difficult. First, find a mapping function from the distorted image to the undistorted image. Then use the remap function.

# undistort
mapx, mapy = cv.initUndistortRectifyMap(mtx, dist, None, newcameramtx, (w,h), 5)
dst = cv.remap(img, mapx, mapy, cv.INTER_LINEAR)
# crop the image
x, y, w, h = roi
dst = dst[y:y+h, x:x+w]
cv.imwrite('calibresult.png', dst)

[링크 : https://docs.opencv.org/4.x/dc/dbb/tutorial_py_calibration.html]

 

Parameters
rvecs Output vector of rotation vectors (Rodrigues ) estimated for each pattern view (e.g. std::vector<cv::Mat>>). That is, each i-th rotation vector together with the corresponding i-th translation vector (see the next output parameter description) brings the calibration pattern from the object coordinate space (in which object points are specified) to the camera coordinate space. In more technical terms, the tuple of the i-th rotation and translation vector performs a change of basis from object coordinate space to camera coordinate space. Due to its duality, this tuple is equivalent to the position of the calibration pattern with respect to the camera coordinate space.
tvecs Output vector of translation vectors estimated for each pattern view, see parameter describtion above.
stdDeviationsIntrinsics Output vector of standard deviations estimated for intrinsic parameters. Order of deviations values: (fx,fy,cx,cy,k1,k2,p1,p2,k3,k4,k5,k6,s1,s2,s3,s4,τx,τy) If one of parameters is not estimated, it's deviation is equals to zero.
stdDeviationsExtrinsics Output vector of standard deviations estimated for extrinsic parameters. Order of deviations values: (R0,T0,…,RM−1,TM−1) where M is the number of pattern views. Ri,Ti are concatenated 1x3 vectors.
perViewErrors Output vector of the RMS re-projection error estimated for each pattern view.

Returns
the overall RMS re-projection error.

[링크 : https://docs.opencv.org/4.x/d9/d0c/group__calib3d.html#ga3207604e4b1a1758aa66acb6ed5aa65d]

 

+

테스트 이미지를 보정해서 저장하도록 수정

$ cat calib.py 
import cv2
import numpy as np
import os
import glob
# 체커보드의 차원 정의
CHECKERBOARD = (6,9) # 체커보드 행과 열당 내부 코너 수
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
# 각 체커보드 이미지에 대한 3D 점 벡터를 저장할 벡터 생성
objpoints = []
# 각 체커보드 이미지에 대한 2D 점 벡터를 저장할 벡터 생성
imgpoints = [] 
# 3D 점의 세계 좌표 정의
objp = np.zeros((1, CHECKERBOARD[0] * CHECKERBOARD[1], 3), np.float32)
objp[0,:,:2] = np.mgrid[0:CHECKERBOARD[0], 0:CHECKERBOARD[1]].T.reshape(-1, 2)
prev_img_shape = None
# 주어진 디렉터리에 저장된 개별 이미지의 경로 추출
images = glob.glob('./images/*.jpg')
for fname in images:
    img = cv2.imread(fname)
    # 그레이 스케일로 변환
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    # 체커보드 코너 찾기
    # 이미지에서 원하는 개수의 코너가 발견되면 ret = true
    ret, corners = cv2.findChessboardCorners(gray,
                                             CHECKERBOARD,
                                             cv2.CALIB_CB_ADAPTIVE_THRESH + cv2.CALIB_CB_FAST_CHECK + cv2.CALIB_CB_NORMALIZE_IMAGE)
    # 원하는 개수의 코너가 감지되면,
    # 픽셀 좌표 미세조정 -> 체커보드 이미지 표시
    if ret == True:
        objpoints.append(objp)
        # 주어진 2D 점에 대한 픽셀 좌표 미세조정
        corners2 = cv2.cornerSubPix(gray, corners, (11,11),(-1,-1), criteria)
        imgpoints.append(corners2)
        # 코너 그리기 및 표시
        img = cv2.drawChessboardCorners(img, CHECKERBOARD, corners2, ret)
    cv2.imshow('img',img)
    cv2.waitKey(0)
cv2.destroyAllWindows()

h,w = img.shape[:2] # 480, 640
# 알려진 3D 점(objpoints) 값과 감지된 코너의 해당 픽셀 좌표(imgpoints) 전달, 카메라 캘리브레이션 수행
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)

images = glob.glob('./images/*.jpg')
for fname in images:
    img = cv2.imread(fname)

    h,  w = img.shape[:2]
    newcameramtx, roi = cv2.getOptimalNewCameraMatrix(mtx, dist, (w,h), 1, (w,h))

    dst = cv2.undistort(img, mtx, dist, None, newcameramtx)
    # crop the image
    x, y, w, h = roi
    dst = dst[y:y+h, x:x+w]
    print(fname+'.undisto')
    cv2.imwrite(fname+'.undisto.jpg', dst)

 

2760p 노트북에 달린 웹캠 720p로 해봤는데

먼가 꼼지락 대는거 보면 왜곡이 보정된 것 같기도 하고.. 아닌것 같기도 하고 모르겠다 ㅎㅎ

'Programming > openCV' 카테고리의 다른 글

opencv stereo 계산 알고리즘  (0) 2024.02.24
opencv 스테레오 카메라 깊이 처리하기  (0) 2024.02.21
opencv 카메라 캡쳐 - 최신 이미지 갱신  (0) 2024.01.25
opencv webcam 수동촛점 조절  (0) 2024.01.25
MTM + webcam  (0) 2024.01.16
Posted by 구차니
Programming/golang2024. 2. 20. 18:59

처음에는 이해를 못하고 넘겼는데, "런타임에 타입정보를 얻는" 이라고 하니 감이온다.

[링크 : http:// https://zetawiki.com/wiki/리플렉션,_리플렉티브_프로그래밍]

 

인터프리트 언어에서 성능 향상을 위해 런타임시 타입을 추적하는게 있었는데

그거 랑 유사하게 컴파일 언어지만 런타임 최적화를 위해서 추가된 기능이려나?

 

다만 리플렉트는 자바에서 온 듯

[링크 : https://a07274.tistory.com/m/53]

[링크 : https://pyrasis.com/book/GoForTheReallyImpatient/Uni6]

 

'Programming > golang' 카테고리의 다른 글

golang tcp socket timeout 주기(listen, read)  (0) 2024.04.08
golang echo i18n  (0) 2024.02.19
golang package  (0) 2024.02.19
golang html/template ParseFiles()  (0) 2024.02.16
golang runtime.GOMAXPROCS()  (0) 2024.02.15
Posted by 구차니
Programming/golang2024. 2. 19. 15:22

echo 라이브러리에서도 i18n(다국어 지원)이 가능하단다.

근데 결국에는 이걸 쓰려면 템플릿을 이용해서 쇼를 해야하고,

템플릿은 서버 사이드에서 렌더링 해주는거라, 이래저래 매번 프로세싱을 해야 하는것도 부담이니

클라이언트 사이드에서 문자열 치환해서 넣는 방식으로 가야할 듯.

 

[링크 : https://phrase.com/blog/posts/internationalisation-in-go-with-go-i18n/]

[링크 : https://www.alexedwards.net/blog/i18n-managing-translations]

'Programming > golang' 카테고리의 다른 글

golang tcp socket timeout 주기(listen, read)  (0) 2024.04.08
golang reflect  (0) 2024.02.20
golang package  (0) 2024.02.19
golang html/template ParseFiles()  (0) 2024.02.16
golang runtime.GOMAXPROCS()  (0) 2024.02.15
Posted by 구차니
Programming/vue.js2024. 2. 19. 15:18

vue.js 에서도 다국어 지원이 가능하다.

json으로 문자열 테이블을 만들어야 하는게 조금 귀찮아 보이는데

과거 poedit 처럼 단수/복수에 대한 문장을 하나의 메시지에 넣어서 쓸 수 있어 좀 더 편해 보인다.

 

csv -> json 변환툴을 찾거나 만들면 서로 좀 편하게 작업이 가능할 듯.

 

[링크 : https://jollyworker.co.kr/vue-js를-활용한-다국어-지원-구현하기/]

[링크 : https://lily-choi.tistory.com/5]

'Programming > vue.js' 카테고리의 다른 글

vue import "@"  (0) 2024.04.19
vue webpack ckeditor  (0) 2024.04.19
vue3 ckeditor5 document editor 추가하기  (0) 2024.04.18
vue 입력창 포커스 설정  (0) 2024.03.28
vue proxy  (0) 2024.03.26
Posted by 구차니
Programming/golang2024. 2. 19. 14:00

내가 잘 못 쓰고 있는 느낌인데..

아래와 같은 구조로 되어서 디렉토리당 하나의 패키지만 존재해야 하는 것 같다.

main.go
test1/
    rest.go
test2/
    template.go

 

main.go 에서는

import에서 디렉토리 명을 적으면 되고

vscode 지원을 받으면 자동으로 아래처럼 별칭을 붙여준다.

import (
rest_handler "was_test/test1"
template_handler "was_test/test2"
)

'Programming > golang' 카테고리의 다른 글

golang reflect  (0) 2024.02.20
golang echo i18n  (0) 2024.02.19
golang html/template ParseFiles()  (0) 2024.02.16
golang runtime.GOMAXPROCS()  (0) 2024.02.15
golang echo 템플릿 파일로 불러오기  (0) 2024.02.14
Posted by 구차니
Programming/golang2024. 2. 16. 11:44

아래의 붉은 부분에 대한 해석이 필요해서 검색

func main() {
  // Echo instance
  e := echo.New()

  // Instantiate a template registry with an array of template set
  // Ref: https://gist.github.com/rand99/808e6e9702c00ce64803d94abff65678
  templates := make(map[string]*template.Template)
  templates["home.html"] = template.Must(template.ParseFiles("view/home.html", "view/base.html"))
  templates["about.html"] = template.Must(template.ParseFiles("view/about.html", "view/base.html"))
  e.Renderer = &TemplateRegistry{
    templates: templates,
  }

  // Route => handler
  e.GET("/", handler.HomeHandler)
  e.GET("/about", handler.AboutHandler)

  // Start the Echo server
  e.Logger.Fatal(e.Start(":1323"))
}

[링크 : https://gitlab.com/ykyuen/golang-echo-template-example/-/blob/master/main.go?ref_type=heads]

[링크 : https://gitlab.com/ykyuen/golang-echo-template-example]

[링크 : https://dev.to/ykyuen/setup-nested-html-template-in-go-echo-web-framework-e9b]

 

ParseFiles() 는 가장 마지막 파일이 결과로 나온다.

다르게 해석하면 앞에서 부터 웹 레이아웃 구성요소들로 넣고, 가장 마지막에 페이지 하나에 대한 템플릿을 두면 된다.

func (*Template) ParseFiles ¶
func (t *Template) ParseFiles(filenames ...string) (*Template, error)
ParseFiles parses the named files and associates the resulting templates with t. If an error occurs, parsing stops and the returned template is nil; otherwise it is t. There must be at least one file.

When parsing multiple files with the same name in different directories, the last one mentioned will be the one that results.

ParseFiles returns an error if t or any associated template has already been executed.

[링크 : https://pkg.go.dev/html/template#Template.ParseFiles]

'Programming > golang' 카테고리의 다른 글

golang echo i18n  (0) 2024.02.19
golang package  (0) 2024.02.19
golang runtime.GOMAXPROCS()  (0) 2024.02.15
golang echo 템플릿 파일로 불러오기  (0) 2024.02.14
golang switch  (0) 2024.02.08
Posted by 구차니
Programming/golang2024. 2. 15. 09:22

golang은 1개 cpu만 쓰도록 되어 있다는데

요즘 버전에서는 어떻게 바뀌었나 확인은 필요할 것 같다.

 

해보니 전체 코어 갯수 만큼 돌리도록 설정되는 듯. (go 1.20.4에서 테스트)

func GOMAXPROCS ¶
func GOMAXPROCS(n int) int
GOMAXPROCS sets the maximum number of CPUs that can be executing simultaneously and returns the previous setting. It defaults to the value of runtime.NumCPU. If n < 1, it does not change the current setting. This call will go away when the scheduler improves.

func

 

 

[링크 : https://pkg.go.dev/runtime#NumCPU]

[링크 : https://pkg.go.dev/runtime#GOMAXPROCS]

 

[링크 : https://pyrasis.com/book/GoForTheReallyImpatient/Unit33/01]

 

 

'Programming > golang' 카테고리의 다른 글

golang package  (0) 2024.02.19
golang html/template ParseFiles()  (0) 2024.02.16
golang echo 템플릿 파일로 불러오기  (0) 2024.02.14
golang switch  (0) 2024.02.08
golang switch - fallthrough  (0) 2024.02.08
Posted by 구차니