import cv2
import numpy as np
from PyQt5.QtWidgets import QFileDialog, QApplication
import sys
import zoom_pixel_viewer as pv
def nothing(x):
pass
cv2.namedWindow('Image Process',cv2.WINDOW_NORMAL)
cv2.resizeWindow('Image Process',500,800)
hh='Max'
hl='Min'
wnd = 'Image Process'
app = QApplication(sys.argv)
filenames, filetype = QFileDialog.getOpenFileName()
PATH = filenames
cv2.createTrackbar("Max", "Image Process",0,255,nothing)
cv2.setTrackbarPos("Max", "Image Process",180)
cv2.createTrackbar("Min", "Image Process",0,255,nothing)
cv2.setTrackbarPos("Min", "Image Process",78)
cv2.createTrackbar("Blur", "Image Process",0,20,nothing)
cv2.createTrackbar("Dilation", "Image Process",0,5,nothing)
cv2.createTrackbar("Erosion", "Image Process",0,5,nothing)
cv2.createTrackbar("Zoom", "Image Process",1,10,nothing)
cv2.createTrackbar("scale_percent","Image Process",90,110,nothing)
cv2.setTrackbarPos("scale_percent", "Image Process",100)
cv2.createTrackbar("MedianFilter", "Image Process",0,10,nothing)
cv2.createTrackbar("contourMax", "Image Process",0,255,nothing)
cv2.createTrackbar("contourMin", "Image Process",0,255,nothing)
cv2.createTrackbar("Gamma correct", "Image Process",0,20,nothing)
cv2.setTrackbarPos("Gamma correct", "Image Process",10)
cv2.createTrackbar("Filter_CA_low", "Image Process",0,10000,nothing)
cv2.createTrackbar("Filter_CA_max", "Image Process",0,500000,nothing)
cv2.setTrackbarPos("Filter_CA_max", "Image Process",500000)
cv2.createTrackbar("max_height", "Image Process",0,3000,nothing)
cv2.setTrackbarPos("max_height", "Image Process",3000)
cv2.createTrackbar("low_height", "Image Process",0,100,nothing)
cv2.setTrackbarPos("low_height", "Image Process",0)
cv2.createTrackbar("BINAY_INV", "Image Process",0,1,nothing)
cv2.createTrackbar("Color", "Image Process",0,2,nothing)
cv2.createTrackbar("ClipLimit", "Image Process",0,100,nothing)
cv2.createTrackbar("TileGridSize", "Image Process",0,50,nothing)
cv2.createTrackbar("Max_graylevel", "Image Process",0,255,nothing)
cv2.setTrackbarPos("Max_graylevel", "Image Process",255)
img = cv2.imdecode(np.fromfile(PATH, dtype=np.uint8),cv2.IMREAD_COLOR)
temp_img = np.copy(img)
img = cv2.resize(img, (0,0), fx=1, fy=1)
while(1):
#image前处理
hul=cv2.getTrackbarPos("Min", "Image Process")
huh=cv2.getTrackbarPos("Max", "Image Process")
b = cv2.getTrackbarPos("Blur", "Image Process")
d = cv2.getTrackbarPos("Dilation", "Image Process")
e = cv2.getTrackbarPos("Erosion", "Image Process")
f = cv2.getTrackbarPos("Zoom", "Image Process")
m = cv2.getTrackbarPos("MedianFilter", "Image Process")
g = cv2.getTrackbarPos("Gamma correct", "Image Process")
canny_max=cv2.getTrackbarPos("contourMax", "Image Process")
canny_min=cv2.getTrackbarPos("contourMin", "Image Process")
CA_low = cv2.getTrackbarPos("Filter_CA_low", "Image Process")
CA_max = cv2.getTrackbarPos("Filter_CA_max", "Image Process")
max_height = cv2.getTrackbarPos("max_height", "Image Process")
low_height = cv2.getTrackbarPos("low_height", "Image Process")
BINAY_INV = cv2.getTrackbarPos("BINAY_INV", "Image Process")
Color = cv2.getTrackbarPos("Color", "Image Process")
Clip = cv2.getTrackbarPos("ClipLimit", "Image Process")
GridSize = cv2.getTrackbarPos("TileGridSize", "Image Process")
Max_graylevel = cv2.getTrackbarPos("Max_graylevel", "Image Process")
scale_percent = cv2.getTrackbarPos("scale_percent","Image Process")
#resize
scale_percent = 104.1
width = int(img.shape[1]*scale_percent/100)
height = int(img.shape[0]*scale_percent/100)
dim = (width,height)
resized = cv2.resize(img, dim, interpolation = cv2.INTER_AREA)
#Gamma 校正
gamma = g # gamma < 1 增強暗部,gamma > 1 增強亮部
gamma_corrected = np.power(resized / 255, (gamma/10) ) * 255
gamma_corrected = np.uint8(gamma_corrected)
#其他预处理
thresh1 = cv2.GaussianBlur(gamma_corrected,(3,3),b)
kernel = np.ones((3,3),np.uint8)
thresh1 = cv2.dilate(thresh1,kernel,iterations=d)
thresh1 = cv2.erode(thresh1,kernel,iterations=e)
thresh1 = cv2.medianBlur(thresh1,(2*m+1))
thresh1 = cv2.cvtColor(thresh1, cv2.COLOR_BGR2GRAY)
print (thresh1.dtype)
try:
clahe = cv2.createCLAHE(clipLimit=Clip, tileGridSize=(GridSize,GridSize))
thresh1 = clahe.apply(thresh1)
except:
pass
ret,thresh2 = cv2.threshold(thresh1,hul,huh,cv2.THRESH_BINARY_INV)
#EDGE DETECTION
edges = cv2.Canny(thresh1,canny_min,canny_max)
edges = 255 - edges #black -> whitecv
edges_COLOR = cv2.cvtColor(edges,cv2.COLOR_GRAY2RGB)
if Color == 0 :
edges_COLOR[np.where((edges_COLOR==[0,0,0]).all(axis=2))] = [255,0,0]
if Color == 1 :
edges_COLOR[np.where((edges_COLOR==[0,0,0]).all(axis=2))] = [0,255,0]
if Color == 2 :
edges_COLOR[np.where((edges_COLOR==[0,0,0]).all(axis=2))] = [0,0,255]
Conv_hsv_Gray = thresh2
if BINAY_INV == 1 :
ret, mask2 = cv2.threshold(Conv_hsv_Gray, 0, 255,cv2.THRESH_BINARY_INV |cv2.THRESH_OTSU)
else:
ret, mask2 = cv2.threshold(Conv_hsv_Gray, 0, 255,cv2.THRESH_BINARY |cv2.THRESH_OTSU)
contours , hierarchy = cv2.findContours(mask2,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
filtered_contours = []
for contour in contours:
area = cv2.contourArea(contour)
x,y,w,h = cv2.boundingRect(contour)
if area > CA_low and h < max_height and area < CA_max and low_height < h : # 根據實際圖像調整閾值
filtered_contours.append(contour)
areas = [cv2.contourArea(contour) for contour in filtered_contours]
total_area = sum(areas)
# 在圖像上繪製輪廓並標註面積
'''
filtered_contours_2 = []
for cnt in filtered_contours:
if h < max_height:
filtered_contours_2.append(cnt)
'''
output_img=resized
contour_img = np.ones_like(resized,dtype=np.uint8)*255 #创建空白图像 取过滤后的contour
if Color == 0:
cv2.drawContours(contour_img, filtered_contours, -1,(255,0,0) ,1)
if Color == 1:
cv2.drawContours(contour_img, filtered_contours, -1,(0,255,0) ,1)
if Color == 2:
cv2.drawContours(contour_img, filtered_contours, -1,(0,0,255) ,1)
thresh1 = cv2.cvtColor(thresh1,cv2.COLOR_GRAY2RGB)
#img2 = edges_COLOR
img2 = contour_img #换过滤后的contour
#img1 = gamma_corrected
img1 = thresh1
img1 = resized
rows,cols,channels = img2.shape
roi = img1[0:rows,0:cols]
img2gray = cv2.cvtColor(img2,cv2.COLOR_BGR2GRAY)
#ret, mask = cv2.threshold(img2gray,175,255,cv2.THRESH_BINARY)
ret, mask = cv2.threshold(img2gray,0,255,cv2.THRESH_BINARY|cv2.THRESH_OTSU)
mask_inv = cv2.bitwise_not(mask)
img1_bg = cv2.bitwise_and(roi,roi,mask = mask)
img2_fg = cv2.bitwise_and(img2,img2,mask = mask_inv)
dst = cv2.add(img1_bg,img2_fg)
#ret,thresh2 = cv2.threshold(img,hul,huh,cv2.THRESH_BINARY_INV)
#ret,thresh3 = cv2.threshold(img,hul,huh,cv2.THRESH_TRUNC)
#ret,thresh4 = cv2.threshold(img,hul,huh,cv2.THRESH_TOZERO)
#ret,thresh5 = cv2.threshold(img,hul,huh,cv2.THRESH_TOZERO_INV)
dst = cv2.resize(dst, (0,0), fx=0.5+(f/10), fy=0.5+(f/10))
edges_COLOR = cv2.resize(edges_COLOR, (0,0), fx=0.5+(f/10), fy=0.5+(f/10))
thresh1 = cv2.resize(thresh1, (0,0), fx=0.5+(f/10), fy=0.5+(f/10))
contour_img = cv2.resize(contour_img, (0,0), fx=0.5+(f/10), fy=0.5+(f/10))
image1=contour_img
lower_white = np.array([230,230, 230]) # 白色下界,可調整
upper_white = np.array([255, 255, 255]) # 白色上界
mask1 = cv2.inRange(image1, lower_white, upper_white) # 白色區域為 255,其他為 0
#mask2 = cv2.inRange(image2, lower_white, upper_white) # 白色區域為 255,其他為 0
# 將遮罩中白色區域在原圖上反轉為黑色
result1 = image1.copy()
#result2 = image2.copy()
result1[mask1 == 255] = [0, 0, 0] # 將白色區域設為黑色 (RGB = 0, 0, 0)
cv2.imshow("Chlaeenhance",thresh1)
cv2.imshow("Contour",edges_COLOR)
cv2.imshow("Img_contour",dst)
cv2.imshow("contour_filter",result1)
#cv2.imshow("Conv_hsv_Gray",Conv_hsv_Gray)
#cv2.imshow("thresh4",thresh4)
#cv2.imshow("thresh5",thresh5)
k = cv2.waitKey(1) & 0xFF
if k == ord ('a'):
pv.show(dst)
#pv.show(result1)
if k == ord ('s'):
#cv2.imwrite(PATH[0:-4]+'_BINARY.jpg',thresh1)
#cv2.imwrite(PATH[0:-4]+'_contour_filter.jpg',contour_img)
cv2.imwrite(PATH[0:-4]+'_contour_filter_black.png',result1)
cv2.imwrite(PATH[0:-4]+'_dst.png',dst)
if k == ord ('m'):
while(1):
dst2 = dst.copy()
edges_COLOR2 = edges_COLOR.copy()
# 全局变量
g_window_name = "img" # 窗口名
g_window_wh = [800, 800] # 窗口宽高
g_location_win = [0, 0] # 相对于大图,窗口在图片中的位置
location_win = [0, 0] # 鼠标左键点击时,暂存g_location_win
g_location_click, g_location_release = [0, 0], [0, 0] # 相对于窗口,鼠标左键点击和释放的位置
g_zoom, g_step = 1, 0.1 # 图片缩放比例和缩放系数
g_image_original = edges_COLOR2 # 原始图片,建议大于窗口宽高(800*600)
g_image_zoom = g_image_original.copy() # 缩放后的图片
g_image_show = g_image_original[g_location_win[1]:g_location_win[1] + g_window_wh[1], g_location_win[0]:g_location_win[0] + g_window_wh[0]] # 实际显示的图片
# 矫正窗口在图片中的位置
# img_wh:图片的宽高, win_wh:窗口的宽高, win_xy:窗口在图片的位置
def check_location(img_wh, win_wh, win_xy):
for i in range(2):
if win_xy[i] < 0:
win_xy[i] = 0
elif win_xy[i] + win_wh[i] > img_wh[i] and img_wh[i] > win_wh[i]:
win_xy[i] = img_wh[i] - win_wh[i]
elif win_xy[i] + win_wh[i] > img_wh[i] and img_wh[i] < win_wh[i]:
win_xy[i] = 0
print(img_wh, win_wh, win_xy)
# 计算缩放倍数
# flag:鼠标滚轮上移或下移的标识, step:缩放系数,滚轮每步缩放0.1, zoom:缩放倍数
def count_zoom(flag, step, zoom):
if flag > 0: # 滚轮上移
zoom += step
if zoom > 1 + step * 20: # 最多只能放大到3倍
zoom = 1 + step * 20
else: # 滚轮下移
zoom -= step
if zoom < step: # 最多只能缩小到0.1倍
zoom = step
zoom = round(zoom, 2) # 取2位有效数字
return zoom
def on_checkbox(state, userdata):
print (f"Checkbox state: { 'Checked' if state else 'Unchecked'}")
# OpenCV鼠标事件
def mouse(event, x, y, flags, param):
global g_location_click, g_location_release, g_image_show, g_image_zoom, g_location_win, location_win, g_zoom
if event == cv2.EVENT_LBUTTONDOWN: # 左键点击
g_location_click = [x, y] # 左键点击时,鼠标相对于窗口的坐标
location_win = [g_location_win[0], g_location_win[1]] # 窗口相对于图片的坐标,不能写成location_win = g_location_win
elif event == cv2.EVENT_MOUSEMOVE and (flags & cv2.EVENT_FLAG_LBUTTON): # 按住左键拖曳
g_location_release = [x, y] # 左键拖曳时,鼠标相对于窗口的坐标
h1, w1 = g_image_zoom.shape[0:2] # 缩放图片的宽高
w2, h2 = g_window_wh # 窗口的宽高
show_wh = [0, 0] # 实际显示图片的宽高
if w1 < w2 and h1 < h2: # 图片的宽高小于窗口宽高,无法移动
show_wh = [w1, h1]
g_location_win = [0, 0]
elif w1 >= w2 and h1 < h2: # 图片的宽度大于窗口的宽度,可左右移动
show_wh = [w2, h1]
g_location_win[0] = location_win[0] + g_location_click[0] - g_location_release[0]
elif w1 < w2 and h1 >= h2: # 图片的高度大于窗口的高度,可上下移动
show_wh = [w1, h2]
g_location_win[1] = location_win[1] + g_location_click[1] - g_location_release[1]
else: # 图片的宽高大于窗口宽高,可左右上下移动
show_wh = [w2, h2]
g_location_win[0] = location_win[0] + g_location_click[0] - g_location_release[0]
g_location_win[1] = location_win[1] + g_location_click[1] - g_location_release[1]
check_location([w1, h1], [w2, h2], g_location_win) # 矫正窗口在图片中的位置
g_image_show = g_image_zoom[g_location_win[1]:g_location_win[1] + show_wh[1], g_location_win[0]:g_location_win[0] + show_wh[0]] # 实际显示的图片
elif event == cv2.EVENT_MOUSEWHEEL: # 滚轮
z = g_zoom # 缩放前的缩放倍数,用于计算缩放后窗口在图片中的位置
g_zoom = count_zoom(flags, g_step, g_zoom) # 计算缩放倍数
w1, h1 = [int(g_image_original.shape[1] * g_zoom), int(g_image_original.shape[0] * g_zoom)] # 缩放图片的宽高
w2, h2 = g_window_wh # 窗口的宽高
g_image_zoom = cv2.resize(g_image_original, (w1, h1), interpolation=cv2.INTER_AREA) # 图片缩放
show_wh = [0, 0] # 实际显示图片的宽高
if w1 < w2 and h1 < h2: # 缩放后,图片宽高小于窗口宽高
show_wh = [w1, h1]
cv2.resizeWindow(g_window_name, w1, h1)
elif w1 >= w2 and h1 < h2: # 缩放后,图片高度小于窗口高度
show_wh = [w2, h1]
cv2.resizeWindow(g_window_name, w2, h1)
elif w1 < w2 and h1 >= h2: # 缩放后,图片宽度小于窗口宽度
show_wh = [w1, h2]
cv2.resizeWindow(g_window_name, w1, h2)
else: # 缩放后,图片宽高大于窗口宽高
show_wh = [w2, h2]
cv2.resizeWindow(g_window_name, w2, h2)
g_location_win = [int((g_location_win[0] + x) * g_zoom / z - x), int((g_location_win[1] + y) * g_zoom / z - y)] # 缩放后,窗口在图片的位置
check_location([w1, h1], [w2, h2], g_location_win) # 矫正窗口在图片中的位置
# print(g_location_win, show_wh)
g_image_show = g_image_zoom[g_location_win[1]:g_location_win[1] + show_wh[1], g_location_win[0]:g_location_win[0] + show_wh[0]] # 实际的显示图片
cv2.imshow(g_window_name, g_image_show)
# 主函数
if __name__ == "__main__":
# 设置窗口
cv2.namedWindow(g_window_name, cv2.WINDOW_NORMAL)
# 设置窗口大小,只有当图片大于窗口时才能移动图片
cv2.resizeWindow(g_window_name, g_window_wh[0], g_window_wh[1])
cv2.moveWindow(g_window_name, 700, 100) # 设置窗口在电脑屏幕中的位置
# 鼠标事件的回调函数
cv2.setMouseCallback(g_window_name, mouse)
#cv2.waitKey(0) # 不可缺少,用于刷新图片,等待鼠标操作
#cv2.destroyAllWindows()
elif k == 27: #wait for ESC key to exit
break
if k == 27: #wait for ESC key to exit
img= temp_img
img = cv2.resize(img, (0,0), fx=2, fy=2)
break
# elif k == 27: #wait for ESC key to exit
# break
if cv2.getWindowProperty("Chlaeenhance", cv2.WND_PROP_VISIBLE) < 1 :
break
if cv2.getWindowProperty("Contour", cv2.WND_PROP_VISIBLE) < 1 :
break
if cv2.getWindowProperty("Img_contour", cv2.WND_PROP_VISIBLE) < 1 :
break
cv2.destroyAllWindows()
****解读一下这个程序
最新发布