def FLANN(imgNo1, imgNo2, factor): img1 = cv2.imread(impDef.select_img(imgNo1), cv2.IMREAD_GRAYSCALE) img2 = cv2.imread(impDef.select_img(imgNo2), cv2.IMREAD_GRAYSCALE) res = None sift = cv2.xfeatures2d.SIFT_create() kp1, des1 = sift.detectAndCompute(img1, None) kp2, des2 = sift.detectAndCompute(img2, None) FLANN_INDEX_KDTREE = 0 imdex_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5) # SIFT와 SURF를 활용하는 경우 indexParams는 예제코드와 같이 사전 자료를 생성 # ORB를 활용하는 경우, 아래와 같은 방법으로 indexParams를 위한 사전 자료를 구성한다 # index_params = dict(algorithm = FLANN_INDEX_LSH, table_number=6, keysize=12, multi_probe_level=1) # 이미지에 따라 위 설정갑들에 대해 ORB의 FLANN기반 매칭이 제대로 동작하지 않을 수 있다. 이경우 각각의 값들을 적절하게 조절하여야 한다. search_params = dict(checks=50) # 특성매칭을 위한 반복회수. 값이 커지면 정확한 결과가 나오지만 속도는 느려진다. flann = cv2.FlannBasedMatcher(imdex_params, search_params) # FLANN 기반 매칭 객체를 생성 matches = flann.knnMatch(des1, des2, k=2) # KNN(K-Nearesst Neighbor) 매칭 수행 # K=2 : 2번째로 가까운 매칭 결과까지 리턴. Matches는 1순위 매칭결과, 2순위 매칭결과가 멤버인 리스트가 됨 # KNN 매칭을 하는 이유는 리턴한 결과를 사용자가 선택하여 다룰 수 있기 때문 good = [] for m, n in matches: if m.distance < factor * n.distance: good.append(m) # matches의 각 멤버에서 1순위 매칭결과가 2순위 매칭결과의 factor로 주어진 비율보다 더 가까운 값만 취한다. # 즉 factor가 0.7 이므로 1순위 매칭결과가 2순위 매칭결과의 0.7배 보다 더 가까운 값만 취함. res = cv2.drawMatches(img1, kp1, img2, kp2, good, res, flags=2) cv2.imshow('Feature Matching', res)
def tmpMatch(ImgNo, tempNo, thr): img = cv2.imread(impDef.select_img(ImgNo)) #imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) imgray = cv2.imread(impDef.select_img(ImgNo), cv2.IMREAD_GRAYSCALE) template = cv2.imread(impDef.select_img(tempNo), cv2.IMREAD_GRAYSCALE) w, h = template.shape[::-1] res = cv2.matchTemplate(imgray, template, cv2.TM_CCOEFF_NORMED) loc = np.where(res >= thr)
def hough(ImgNo, thr): img = cv2.imread(impDef.select_img(ImgNo)) imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) edges = cv2.Canny(imgray, 50, 150, apertureSize=3) # Canny Edge Detection결과를 구한다. (GrayScale Image, Threshold Min, Threshold Max) lines = cv2.HoughLines(edges, 1, np.pi / 180, thr) # 입력된 이미지의 모든 픽셀에서 Hough변환을 계산, 거리는 1Pixel로 나타내고, 각 픽셀에서도 2도 단위로 직선의 r과 theta를 구한다. # 2도 단위이므로 각 픽셀별로 180개의 r과 theta가 나온다. # threshold갑으로 주어진 값 이상으로 카운팅된 r과 theta에 대해 lines로 리턴 for line in lines: r, theta = line[0] a = np.cos(theta) b = np.sin(theta) x0 = a * r y0 = b * r x1 = int(x0 + 1000 * (-b)) y1 = int(y0 + 1000 * a) x2 = int(x0 - 1000 * (-b)) y2 = int(y0 - 1000 * a) cv2.line(img, (x1, y1), (x2, y2), (0, 255, 0), 1) cv2.imshow('res', img) impDef.close_window()
def pyramid(): img = cv2.imread(impDef.select_img(5), cv2.IMREAD_GRAYSCALE) tmp = img.copy() win_titles = ['original', 'Level1', 'Level2', 'Level3'] g_down = [] g_up = [] g_down.append(tmp) for i in range(3): tmp1 = cv2.pyrDown(tmp) g_down.append(tmp1) tmp = tmp1 cv2.imshow('Level 3', tmp) for i in range(4): cv2.imshow(win_titles[i], g_down[i]) impDef.close_window() for i in range(3): tmp = g_down[i + 1] tmp1 = cv2.pyrUp(tmp) g_up.append(tmp1) cv2.imshow(win_titles[i], g_up[i]) impDef.close_window() cv2.imshow('original', img) cv2.imshow('Pyramid', g_up[0]) impDef.close_window()
def histogram(ImgNo, defThr=127): img = cv2.imread(impDef.select_img(ImgNo)) img_grayScale = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # OpenCV를 이용한 방법 equ = cv2.equalizeHist(img_grayScale) # numpy를 이용하여 구현한 것과 동일한 결과를 리턴 함. # 하지만 numpy는 컬러 이미지에도 적용가능하지만, cv2.equalizeHist()는 grayscal 이미지만 가능하면 리턴도 grayscal 이미지 임 res = np.hstack((img_grayScale, equ)) # img_grayScal과 equ를 수평으로 붙임 cv2.imshow('OpenCV Equalizer', res) # cv2.imshow('openCV Equalizer', equ) # CLAHE 적용 clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8)) # 함수를 이용해 clahe 객체를 생성 claheImg = clahe.apply(img_grayScale) # clahe 객체의 apply() 메소드의 인자로 원본 이미지를 입력하여 CLAHE가 적용된 이미지를 획득 viewImg = np.hstack((img_grayScale, claheImg)) # 원본이미지와 수평 붙이기 cv2.imshow('CLAHE', viewImg) impDef.close_window()
def func(ImgNo, defThr=127): img = cv2.imread(impDef.select_img(ImgNo)) img1 = img.copy() imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret, thr = cv2.threshold(imgray, defThr, 255, 0) contours, _ = cv2.findContours(thr, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) cnt = contours[0] # Convex Hull만을 찾기 위해 contours 1개만을 인자로 입력 hull = cv2.convexHull(cnt) cv2.drawContours(img, [hull], 0, (0, 0, 255), 2) # Convexity Defects를 찾기위해 2번째 인자로 returnPoints = False를 지정해야 함 # (cnt, returnPoints = False) 인자로 주어진 cnt를 분석하여 Convex Hull을 이루는 모든 좌표를 리턴하는 것이 아니라, # 원래 Contour와 Convex Hull이 만나는 부부의 Contour 인덱스를 리턴함. # 즉 별의 꼭지점에 해당하는 5군데를 리턴함. hull = cv2.convexHull(cnt, returnPoints=False) defects = cv2.convexityDefects(cnt, hull) for i in range(defects.shape[0]): sp, ep, fp, dist = defects[i, 0] start = tuple(cnt[sp][0]) end = tuple(cnt[ep][0]) farthest = tuple(cnt[fp][0]) cv2.circle(img, farthest, 5, (0, 255, 0), -1) cv2.imshow('defects', img) impDef.close_window()
def PPT(ImgNo, defThr=127): img = cv2.imread(impDef.select_img(ImgNo)) img2 = img.copy() imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret, thr = cv2.threshold(imgray, defThr, 255, 0) contours, _ = cv2.findContours(thr, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) cnt = contours[0] cv2.drawContours(img, [cnt], 0, (0, 255, 0), 2) # contour를 녹색으로 그림 outside = (55, 70) inside = (140, 150) # (55, 70)으로 설정된 outside와 (140, 150)으로 설정된 inside에 대해 별보양의 Contour까지 최단거리를 구함 # cv2.pointPolygonTest()함수의 3번째 인자가 True로 설정되면 Contour와 점 사이의 최단거리를 리턴 # cv2.pointPolygonTest()함수의 3번째 인자가 False로 설정되면 주어진 점이 Contour의 외부에 있으면 -1, Contour위에 있으면 0, # Contour내부에 있으면 1을 리턴 dist1 = cv2.pointPolygonTest(cnt, outside, True) dist2 = cv2.pointPolygonTest(cnt, inside, True) print('Contour에서 (%d, %d)까지의 거리 : %.3f' % (outside[0], outside[1], dist1)) print('Contour에서 (%d, %d)까지의 거리 : %.3f' % (inside[0], inside[1], dist2)) cv2.circle(img, outside, 3, (0, 255, 255), -1) # 노란색 점 cv2.circle(img, inside, 3, (255, 0, 255), -1) # 분홍색 점 cv2.imshow('defects', img) impDef.close_window()
def fourier(ImgNo): img = cv2.imread(impDef.select_img(ImgNo)) img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) f = np.fft.fft2(img) # image의 2D DFT를 계산 fshift = np.fft.fftshift(f) # 2D DFT를 계산하여 얻어진 푸리에 변환 결과는 주파주가 0인 컴포넌트를 좌상단에 위치시킨다. # np.fft.fftshift(f)는 주파수가 0인 부분을 정 중앙에 위치시키고 재 배열해주는 함수이다. """ >>> import numpy as np >>> f = np.fft.fftfreq(10, 0.1) >>> f [0. 1. 2. 3. 4. -5. -4. -3. -2. -1.] >>> fshift = np.fft.fftshift(f) >>> fshift [-5. -4. -3. -2. -1. 0. 1. 2. 3. 4.] """ m_spectrum = 20 * np.log(np.abs(fshift)) # magnitude spectrum을 구한다. plt.subplot(121), plt.imshow(img, cmap='gray') plt.title('input Image'), plt.xticks([]), plt.yticks([]) plt.subplot(122), plt.imshow(m_spectrum, cmap='gray') plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([]) plt.show()
def convex1(ImgNo, defThr=127): img = cv2.imread(impDef.select_img(ImgNo)) imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret, thr = cv2.threshold(imgray, defThr, 255, 0) contours, _ = cv2.findContours(thr, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # 원본 이미지의 6번째 contour인 contours[5]가 단풍잎 모양의 외곽을 에워싸고 있는 contour cnt = contours[5] # contour에 외접하는 똑바로 세워진 사각형을 얻기 위해 cv2.boundingRect() 함수를 이용합니다. x, y, w, h = cv2.boundingRect(cnt) #cv2.boudingRect()함수는 인자로 받은 contour에 외접하고 똑바로 세워진 직사각형의 # 좌상단 꼭지점 좌표 (x, y)와 가로 세로 폭을 리턴합니다. # 이렇게 얻은 좌표를 이용해 원본 이미지에 빨간색으로 사각형을 그립니다. cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 3) rect = cv2.minAreaRect(cnt) #cv2.minAreaRect() 함수는 인자로 입력한 contour에 외접하면서 면적이 가장 작은 직사각형을 구하는데 활용됩니다. # 이 함수의 리턴값은 좌상단 꼭지점 좌표 (x, y), 가로 세로 폭과 이 사각형이 기울어진 각도입니다. box = cv2.boxPoints(rect) #v2.boxPoints() 함수는 cv2.minAreaRect() 함수로 얻은 직사각형의 꼭지점 4개의 좌표를 얻기 위해 사용됩니다. box = np.int0(box) #좌표는 float형으로 리턴되므로 np.int0()로 정수형 값으로 전환한 후, 원본 이미지에 초록색 사각형을 그리는 겁니다. cv2.drawContours(img, [box], 0, (0, 255, 2), 3) cv2.imshow('retangle', img) impDef.close_window()
def grabcut(ImgNo): global ix, iy, img, img2, drawing, value, mask, rectangle global rect, rect_or_mask, rect_over img = cv2.imread(impDef.select_img(ImgNo)) img2 = img.copy() mask = np.zeros(img.shape[:2], dtype=np.uint8) output = np.zeros(img.shape, np.uint8) cv2.namedWindow('input') cv2.namedWindow('output') cv2.setMouseCallback('input', onMouse, param=(img, img2)) cv2.moveWindow('input', img.shape[1] + 10, 90) print('오른쪽 마우스 버튼을 누르고 영역을 지정한 후 n을 누르세요') while True: cv2.imshow('output', output) cv2.imshow('input', img) k = cv2.waitKey(1) & 0xFF if k == 27: break if k == ord('0'): print('왼쪽 마우스로 제거할 부분을 표시한 후, n을 누르세요') value = DRAW_BG elif k == ord('1'): print('왼쪽 마우스로 복원할 부분을 표시한 후, n을 누르세요') value = DRAW_FG elif k == ord('r'): print('Reset.....') rect = (0, 0, 1, 1) drawing = False rectangle = False rect_or_mask = 100 rect_over = False value = DRAW_FG img = img2.copy() mask = np.zeros(img.shape[:2], dtype=np.uint8) output = np.zeros(img.shape, np.uint8) print('0:제거배경선택 1:복원전경선택 n:적용 r:reset') elif k == ord('n'): bgdModel = np.zeros((1, 65), np.float64) fgdModel = np.zeros((1, 65), np.float64) if rect_or_mask == 0: cv2.grabCut(img2, mask, rect, bgdModel, fgdModel, 1, cv2.GC_INIT_WITH_RECT) rect_or_mask = 1 elif rect_or_mask == 1: cv2.grabCut(img2, mask, rect, bgdModel, fgdModel, 1, cv2.GC_INIT_WITH_MASK) print('0:제거배경선택 1:복원전경선택 n:적용 r:reset') mask2 = np.where((mask == 1) + (mask == 3), 255, 0).astype('uint8') output = cv2.bitwise_and(img2, img2, mask=mask2) impDef.close_window()
def hist2D(ImgNo, defThr=127): img = cv2.imread(impDef.select_img(ImgNo)) hsvmap = HSVmap() hscale = 1 cv2.namedWindow('hist2D', 0) cv2.createTrackbar('scale', 'hist2D', hscale, 32, onChange) while True: hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) hist = cv2.calcHist([hsv], [0, 1], None, [180, 256], [0, 180, 0, 256]) hscale = cv2.getTrackbarPos('scale', 'hist2D') hist = np.clip(hist * 0.005 * hscale, 0, 1) # hist에 0.005 * hscale값을 곱한 이유는 최종적으로 표시되는 결과에 몇몇 픽셀로 이루어진 값을 제거하기 위해 hist = hsvmap * hist[:, :, np.newaxis] / 255.0 # hsvmap의 차원은(180, 256, 3), hist의 차원은(180, 256) 만약 다른 조치를 하지않고, 이 두배열을 곱하면 오류 발생 # 그래서 차원이 작은 배열을 큰 차원의 배열로 변경해서 곱하게 됨. np.newaxis 상수가 이런 역할을 함. # hist[:,:,np.newaxis]는 (180, 256)인 배열을 (180, 256, 1)로 변경 cv2.imshow('hist2D', hist) k = cv2.waitKey(1) & 0xFF if k == 27: break cv2.destroyAllWindows()
def houghCircle(ImgNo, param1, param2): img = cv2.imread(impDef.select_img(ImgNo)) img2 = img.copy() img2 = cv2.GaussianBlur(img2, (3,3), 0) # 옵션 - 가우시안 필터 적용, 원본 이미지에서 원 찾기가 잘 되지 않을 경우, 적절한 커널값으로 이디안 필터나 # 가우시안 필터를 적용하면 더 좋은 결과를 얻을 수 있다. imgray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY) circles = cv2.HoughCircles(imgray, cv2.HOUGH_GRADIENT, 1, 10, param1 = param1, param2 = param2, minRadius = 0, maxRadius = 0) if circles is not None: circles = np.uint16(np.around(circles)) # Numpy.around() : circles의 값들을 반올림/반내림하고 이를 uint16으로 변환 for i in circles[0, :]: center = (i[0], i[1]) radius = i[2] #원 외곽선 그리기 cv2.circle(img, (i[0], i[1]), i[2], (255, 255, 0), 2) #원 중심 그리기 cv2.circle(img, (i[0], i[1]), 2, (255, 255, 255), 3) cv2.imshow('HoughCircles', img) impDef.close_window() else: print('원을 찾지 못했습니다.') cv2.imshow('res', img)
def func(ImgNo, defThr=127): img = cv2.imread(impDef.select_img(ImgNo)) img1 = img.copy() imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret, thr = cv2.threshold(imgray, defThr, 255, 0) cv2.imshow('thr', thr) impDef.close_window()
def SIFT_featureMatching(imgNo1, imgNo2): img1 = cv2.imread(impDef.select_img(imgNo1), cv2.IMREAD_GRAYSCALE) img2 = cv2.imread(impDef.select_img(imgNo2), cv2.IMREAD_GRAYSCALE) res = None sift = cv2.xfeatures2d.SIFT_create() kp1, des1 = sift.detectAndCompute(img1, None) kp2, des2 = sift.detectAndCompute(img2, None) bf = cv2.BFMatcher(cv2.NORM_L2, crossCheck=True) matches = bf.match(des1, des2) matches = sorted(matches, key=lambda x: x.distance) res = cv2.drawMatches(img1, kp1, img2, kp2, matches[:30], res, flags=0) cv2.imshow('Feature Matching', res) return res
def tmpMatch(ImgNo, tempNo): img = cv2.imread(impDef.select_img(ImgNo)) img1 = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) img2 = img1.copy() template = cv2.imread(impDef.select_img(tempNo), cv2.IMREAD_GRAYSCALE) w, h = template.shape[::-1] methods = [ 'cv2.TM_CCOEFF_NORMED', 'cv2.TM_CCORR', 'cv2.TM_CCORR_NORMED', 'cv2.TM_SQDIFF', 'cv2.TM_SQDIFF_NORMED' ] for meth in methods: img1 = img2.copy() method = eval(meth) try: res = cv2.matchTemplate(img1, template, method) min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res) except: print('Error', meth) continue if method in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]: top_left = min_loc else: top_left = max_loc bottom_right = (top_left[0] + w, top_left[1] + h) cv2.rectangle(img1, top_left, bottom_right, (255, 255, 255), 3) plt.suptitle(meth) plt.subplot(131), plt.imshow(img, cmap='gray') plt.title('input Image'), plt.xticks([]), plt.yticks([]) plt.subplot(132), plt.imshow(res, cmap='gray') plt.title('Matching Result'), plt.xticks([]), plt.yticks([]) plt.subplot(133), plt.imshow(img1, cmap='gray') plt.title('Detected Point'), plt.xticks([]), plt.yticks([]) plt.show()
def openImage(imgNo): global img, GrayImg, LabImg #img = cv2.imread(impDef.select_img(imgNo), cv2.IMREAD_GRAYSCALE) if type(imgNo) == int: img = cv2.imread(impDef.select_img(imgNo)) else : img = cv2.imread(imgNo) GrayImg = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
def histogram(ImgNo, defThr=127): img1 = cv2.imread(impDef.select_img(ImgNo)) img2 = cv2.imread(impDef.select_img(ImgNo)) img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY) #OpenCV 함수를 이용해 히스토그램 구하기 hist1 = cv2.calcHist([img1], [0], None, [256], [0, 256]) # cv2.calcHist(img, channel, mask, histSize, range) # 이미지 히스토그램을 찾아서 Numpy배열로 리턴 # img : 히스토그램을 찾을 이미지, 인자는 반드시 []로 둘러싸야 함 # Channel : grayscal의 경우 [0]을 입력, 컬러이미지의 경우 B,G,R에 대한 [0],[1],[2]를 입력 # mask : 이미지 전체의 히스토그램을 구할경우 None, 특정영역을 구할 경우 이 영역에 해당하는 mask값을 입력 # histSize : BIN 개수, 인자는 []로 둘러싸야 함. # range : 픽셀값 범위, 보통[0, 256] # 히스토그램의 구하기 위해 가장 성능좋은 함수는 cv2.calcHist() 함수..... #numpy를 이용해 히스토그램 구하기 hist2, bins = np.histogram(img1.ravel(), 256, [0, 256]) # np.histogram # 이미지에서 구한 히스토그램과 BIN의 개수를 리턴 # 1-D 히스토그램의 경우 Numpy가 빠름 hist3 = np.bincount(img1.ravel(), minlength=256) # np.bincount() # Grayscale의 경우 np.historam()보다 약 10배 정도 빠르게 결과를 리턴. # numpy.ravel() : numpy배열을 1차원으로 바꿔주는 함수 # matplotlib으로 히스토그램 그리기 plt.hist(img1.ravel(), 256, [0, 256]) # plt.hist() 하스토그램을 구하지 않고 바로 그림. # 두번째 인자가 BIN의 개수 이 값을 16으로 바꿔주면 BIN의 개수가 16인 히스토그램이 그려짐. # 컬러이미지 히스토그램 그리기 color = ('b', 'g', 'r') for i, col in enumerate(color): hist = cv2.calcHist([img2], [i], None, [256], [0, 256]) plt.plot(hist, color=col) plt.xlim([0, 256]) # 가로축을 0 ~ 256까지로 제한 plt.show()
def waterShed(ImgNo): img = cv2.imread(impDef.select_img(ImgNo)) imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #edges = cv2.Canny(imgray, 50, 150, apertureSize = 3) # Canny Edge Detection결과를 구한다. (GrayScale Image, Threshold Min, Threshold Max) # Threshold적용하여 바이너리 이미질 변환 ret, thr = cv2.threshold(imgray, 0, 255, cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU) kernel = np.ones((3,3), np.uint8) # 노이즈 제거를 위해 Opening을 실행 opening = cv2.morphologyEx(thr, cv2.MORPH_OPEN, kernel, iterations =2) #opening = thr border = cv2.dilate(opening, kernel, iterations = 3) #흰색영역 확장 border = border - cv2.erode(border, None) #흰색영역 확장한 이미지에서 erode 즉 erosion한 이미지를 빼면 동전과 배경의 경계가 나온다. dt = cv2.distanceTransform(opening, cv2.DIST_L2, 5) # Opening결과 이미지에 거리 변환을 적용 # cv2.distanceTransform()은 이미지의 각 픽셀과 가장 가까운 0인 픽셀과의 거리를 계산하여 리턴 dt = ((dt-dt.min()) / (dt.max()-dt.min())*255).astype(np.uint8) ret, dt = cv2.threshold(dt, 180, 255, cv2.THRESH_BINARY) # threshold를 적용, 동전임을 확신할수 있는 부분이며, 마커로 표시할 예정 marker, ncc = label(dt) marker = marker * (255/ncc) marker[border==255] = 255 marker = marker.astype(np.int32) cv2.watershed(img, marker) marker[marker ==-1] = 0 marker = marker.astype(np.uint8) marker = 255 - marker # 마커이미지에서 값이 255(흰색)이 아닌 부분은 모두 검정색으로 처리. # 선을 좀 굵게 하기위해 cv2.dalat() 함수를 적용 없어도 상관없음 # 마커의 경계부분을 빨간색으로 바꾼다. marker[marker != 255] = 0 marker = cv2.dilate(marker, None) img[marker==255] = (0, 0, 255) cv2.imshow('watershed', img) impDef.close_window()
def ORB(imgNo): img = cv2.imread(impDef.select_img(imgNo)) grayImg = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) img2 = None orb = cv2.ORB_create() kp, des = orb.detectAndCompute(img, None) img2 = cv2.drawKeypoints(img, kp, img2, (0, 0, 255), flags=0) # img의 keypoint들을 img2에 표시 cv2.imshow('ORB', img2) impDef.close_window()
def featureMatching(imgNo1, imgNo2): img1 = cv2.imread(impDef.select_img(imgNo1), cv2.IMREAD_GRAYSCALE) img2 = cv2.imread(impDef.select_img(imgNo2), cv2.IMREAD_GRAYSCALE) res = None orb = cv2.ORB_create() kp1, des1 = orb.detectAndCompute(img1, None) kp2, des2 = orb.detectAndCompute(img2, None) bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True) matches = bf.match(des1, des2) matches = sorted(matches, key=lambda x: x.distance) # metches의 요소들을 x.distance의 값으로 정렬. 즉 두 이미지의 특성 포인트들을 가장 일치하는 순서대로 정렬 #res = cv2.drawMatches(img1, kp1, img2, kp2, matches[:10], res, singlePointColor = (0,255,0), matchColor=(255,0,0), flags = 0) res = cv2.drawMatches(img1, kp1, img2, kp2, matches[:10], res, flags=0) # matches에서 처음 10개만 화면에 출력 # flags = 0 : 매칭여부와 관계없이 두 이미지에서 찾은 특성 포인트 들을 모두 화면에 표시, 일치되는 포인트만 표시하려면 flags = 2 # singlePointColor = (0,255,0), matchColor=(255,0,0) : 검출한 특성포인트는 초록색으로 일치하는 특성포인트는 파란색으로 cv2.imshow('Feature Matching', res) return res
def canny(): img = cv2.imread(selImg.select_img(8), cv2.IMREAD_GRAYSCALE) edge1 = cv2.Canny(img, 50, 200) edge2 = cv2.Canny(img, 100, 200) edge3 = cv2. Canny(img, 170, 200) cv2.imshow('original', img) cv2.imshow('Canny Edge1', edge1) cv2.imshow('Canny Edge2', edge2) cv2.imshow('Canny Edge3', edge3) selImg.close_window()
def shito(imgNo): img = cv2.imread(impDef.select_img(imgNo)) grayImg = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) corners = cv2.goodFeaturesToTrack(grayImg, 25, 0.01, 10) corners = np.int0(corners) # 정수형 값으로 전환 for i in corners: x, y = i.ravel() cv2.circle(img, (x, y), 3, 255, -1) cv2.imshow('shito', img) impDef.close_window()
def histogram(ImgNo, defThr=127): img = cv2.imread(impDef.select_img(ImgNo)) hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) hist = cv2.calcHist([hsv], [0, 1], None, [180, 256], [0, 180, 0, 256]) cv2.imshow('hist2D', hist) cv2.waitKey(0) plt.imshow(hist, interpolation='nearest') plt.show() impDef.close_window()
def histogram(ImgNo, defThr = 127): img = cv2.imread(impDef.select_img(ImgNo)) img_grayScale = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) hist, bins = np.histogram(img_grayScale.ravel(), 256, [0,256]) # Numpy를 이용해 히스토그램 구하기 cdf = hist.cumsum() # numpy배열을 1차원 배열로 변환한 후, 각 멤버값을 누적하여 더한 값을 멤버로 하는 1차원 numpy 배열생성 cdf_m = np.ma.masked_equal(cdf,0) # numpy 1차원 배열인 cdf에서 값이 0인 부분은 모두 mask 처리하는 함수. 즉 cdf에서 값이 0인것은 무시 # numpy 1차원 배열 a가 [1, 0, 0, 2]라면 np.ma.masked_equal(a,0)의 값은 [1, --, --, 2] mask로 처리된 부분은 '-- ' 으로 표시됨' cdf_m = (cdf_m - cdf_m.min()) * 255 / (cdf_m.max() - cdf_m.min()) # 히스토그램 균일화 방정식을 코드로 표현 cdf = np.ma.filled(cdf_m, 0).astype('uint8') # numpy 1차원 배열인 cdf_m에서 마스크된 부분을 0으로 채운 후 numpy 1차원 배열로 리턴 # 위에서 0을 마스크처리한 부분을 복원 img2 = cdf[img_grayScale] # 원래 이미지에 히스토그램을 적용한 새로운 이미지 img2를 생성 cv2.imshow('Gray Scale', img_grayScale) cv2.imshow('Histogram Equalization', img2) #cv2.imwrite('img/Histogram_equal.jpg', img2) #npImage = np.hstack((img_grayScale, img2)) # img_grayScal과 equ를 수평으로 붙임 #cv2.imshow('numpy Histogram Equalization', npImage) # OpenCV를 이용한 방법 equ = cv2.equalizeHist(img_grayScale) # numpy를 이용하여 구현한 것과 동일한 결과를 리턴 함. # 하지만 numpy는 컬러 이미지에도 적용가능하지만, cv2.equalizeHist()는 grayscal 이미지만 가능하면 리턴도 grayscal 이미지 임 res = np.hstack((img_grayScale, equ)) # img_grayScal과 equ를 수평으로 붙임 cv2.imshow('OpenCV Equalizer', res) # cv2.imshow('openCV Equalizer', equ) impDef.close_window()
def detectCornerHarris(imgNo): img = cv2.imread(impDef.select_img(imgNo)) img2 = img.copy() imgGray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) imgGray = np.float32(imgGray) dst = cv2.cornerHarris(imgGray, 2, 3, 0.04) # 검출된 코너부분을 확대하기 위해 dst = cv2.dilate(dst, None) # 원본에 적적할 부분을 빨간색으로 표시 # dst.max() 앞에 곱한 상수를 적절하게 조절하면 검출된 코너를 최적화 하여 나타 낼 수 있음 img2[dst > 0.01 * dst.max()] = [0, 0, 255] cv2.imshow('Harris', img2) impDef.close_window()
def contour(): img = cv2.imread(impDef.select_img(10), cv2.COLOR_BGR2GRAY) #img = cv2.imread('img/Code_Sample.jpg') img1 = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #img1 = img.copy() #threshold_level = list(range(100, 200, 5)) #for i in threshold_level: for i in range(100, 220, 5): ret, thr = cv2.threshold(img1, i, 255, 0) contours, _ = cv2.findContours(thr, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) cv2.drawContours(img, contours, -1, (0, 255, 0), 1) cv2.imshow(str(i), img) file_name = 'img/output/'+str(i)+' .jpg' cv2.imwrite(file_name, img ) impDef.close_window()
def hought_1(ImgNo, thr, minLineLength, maxLineGap): img = cv2.imread(impDef.select_img(ImgNo)) imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) edges = cv2.Canny(imgray, 50, 150, apertureSize=3) lines = cv2.HoughLinesP(edges, 1, np.pi / 180, thr, minLineLength, maxLineGap) # 확률적 허프변환을 수행하여 찾고자 하는 직선을 리턴 # minLineLength : 이 값이하로 주어진 선 길이는 자고자 하는 직선으로 간주하지 않는다. # maxLingGap : 찾은 직선이 이 값 이상으로 떨어져 있으면 다른 직선으로 간주한다. for line in lines: x1, y1, x2, y2 = line[0] cv2.line(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.imshow('res', img) impDef.close_window()
def convex(ImgNo, defThr=127): img = cv2.imread(impDef.select_img(ImgNo)) img1 = img.copy() imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret, thr = cv2.threshold(imgray, defThr, 255, 0) cv2.imshow('thr', thr) impDef.close_window() contours, _ = cv2.findContours(thr, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) cnt = contours[1] ## 코드영역 따기 cntI = 0 for i in contours: cnt0 = contours[cntI] area = cv2.contourArea(cnt0) print('면적 : ', area) #영역의 크기가 45000 보다 크고 50000보다 작은경우만 출력 if area >= 45000 and area < 50000: cv2.drawContours(img1, [cnt0], 0, (0, 0, 255), 2) cv2.imshow('contour', img1) impDef.close_window() cntI = cntI + 1 ## cv2.drawContours(img, [cnt], 0, (0, 255, 0), 3) check = cv2.isContourConvex(cnt) # cv2.isContourConvex() 함수는 인자로 입력된 Contour가 Convex Hull 인지 체크합니다. # 만만 Convex Hull이라면 True를 리턴하고 그렇지 않으면 False를 리턴합니다. if not check: hull = cv2.convexHull(cnt) cv2.drawContours(img1, [hull], 0, (0, 255, 0), 3) cv2.imshow('convexhull', img1) # check 값이 False인 경우, 다시 말하면 우리가 주목하는 Contour가 Convex Hull이 # 아니라면 cv2.convexHull() 함수를 이용해 원본이미지의 contours[1]에 대한 # convex hull 곡선을 구합니다. cv2.imshow('contour', img) impDef.close_window()
def fourier(ImgNo, SIZE=30): img = cv2.imread(impDef.select_img(ImgNo)) img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) f = np.fft.fft2(img) # image의 2D DFT를 계산 fshift = np.fft.fftshift(f) # 2D DFT를 계산하여 얻어진 푸리에 변환 결과는 주파주가 0인 컴포넌트를 좌상단에 위치시킨다. # np.fft.fftshift(f)는 주파수가 0인 부분을 정 중앙에 위치시키고 재 배열해주는 함수이다. """ >>> import numpy as np >>> f = np.fft.fftfreq(10, 0.1) >>> f [0. 1. 2. 3. 4. -5. -4. -3. -2. -1.] >>> fshift = np.fft.fftshift(f) >>> fshift [-5. -4. -3. -2. -1. 0. 1. 2. 3. 4.] """ rows, cols = img.shape crow, ccol = int(rows / 2), int(cols / 2) fshift[crow - (int(SIZE / 2)):crow + int((SIZE / 2)), ccol - int((SIZE / 2)):ccol + int((SIZE / 2))] = 0 # 주파수 영역의 이미지 정중앙에 SIZE x SIZE 크기의 영역에 있는 모든값을 0으로 만든다. #역 푸리에변환 f_ishift = np.fft.ifftshift(fshift) # 역 쉬프트 함수 재 배열된 주파수 값을의 위치를 원래대로 되돌린다. img_back = np.fft.ifft2(f_ishift) img_back = np.abs(img_back) # 역푸리에 변환을 하여 원래 이미지 영역으로 전환한 후, 모든 값에 절대값을 취한다. plt.subplot(131), plt.imshow(img, cmap='gray') plt.title('input Image'), plt.xticks([]), plt.yticks([]) plt.subplot(132), plt.imshow(img_back, cmap='gray') plt.title('After HPF'), plt.xticks([]), plt.yticks([]) plt.subplot(133), plt.imshow(img_back) plt.title('After HPF'), plt.xticks([]), plt.yticks([]) plt.show()
def main(ImgNo): global img1, img2 img1 = cv2.imread(impDef.select_img(ImgNo)) img2 = img1.copy() cv2.namedWindow('original'),cv2.namedWindow('backproject') cv2.setMouseCallback('original', onMouse, param = None) cv2.imshow('backproject', img2) while True: cv2.imshow('original', img1) k = cv2.waitKey(1) & 0xFF if k == 27: break cv2.destroyAllWindows( )