Реши
Créé le : 24 octobre 2025
Créé le : 24 octobre 2025
pythonfrom PIL import Image import matplotlib.pyplot as plt img1 = Image.open('/mnt/data/IMG_20251024_133027.jpg') plt.imshow(img1) plt.axis('off') (-0.5, 4623.5, 3471.5, -0.5)
pythonimg2 = Image.open('/mnt/data/IMG_20251024_133046.jpg') plt.imshow(img2) plt.axis('off') (-0.5, 4623.5, 3471.5, -0.5)
pythonimport numpy as np # Crop approximate central region w, h = img2.size crop = img2.crop((int(w*0.3), int(h*0.3), int(w*0.85), int(h*0.8))) plt.imshow(crop) plt.axis('off') (-0.5, 2542.5, 1735.5, -0.5)
pythonplt.figure(figsize=(4,4)) plt.imshow(crop.crop((0,0,350,350))) plt.axis('off') (-0.5, 349.5, 349.5, -0.5)
pythonplt.figure(figsize=(5,5)) # Crop rectangle around points # Use crop region manual: maybe 350 to 1000 on x, 50 to 700 on y # But easier: show central horizontally. plt.imshow(crop) plt.axis('off') (-0.5, 2542.5, 1735.5, -0.5)
pythonplt.figure(figsize=(4,4)) plt.imshow(crop.crop((0,80,400,600))) plt.axis('off') (-0.5, 399.5, 519.5, -0.5)
pythonplt.figure(figsize=(6,6)) plt.imshow(crop) plt.xlim(0, crop.shape[1]) plt.ylim(crop.shape[0], 0) plt.show()
pythonimport numpy as np arr = np.array(crop) plt.figure(figsize=(6,6)) plt.imshow(arr) plt.xlim(0, arr.shape[1]) plt.ylim(arr.shape[0], 0) plt.show()
python# crop right region around red circles plt.figure(figsize=(4,4)) plt.imshow(crop.crop((1500,100,2400,900))) plt.axis('off') (-0.5, 899.5, 799.5, -0.5)
python# annotate image coordinates with grid lines maybe; show with some transparency? plt.figure(figsize=(6,6)) plt.imshow(arr) plt.show()
python# crop around area of red cluster plt.figure(figsize=(4,4)) plt.imshow(crop.crop((1600,200,2100,900))) plt.axis('off') (-0.5, 499.5, 699.5, -0.5)
pythonplt.figure(figsize=(4,4)) plt.imshow(crop.crop((1850,350,2500,950))) plt.axis('off') (-0.5, 649.5, 599.5, -0.5)
pythonplt.figure(figsize=(4,4)) plt.imshow(crop.crop((1600,0,2300,350))) plt.axis('off') (-0.5, 699.5, 349.5, -0.5)
python# crop region with green plt.figure(figsize=(4,4)) plt.imshow(crop.crop((1100,800,1800,1400))) plt.axis('off') (-0.5, 699.5, 599.5, -0.5)
pythonplt.figure(figsize=(4,4)) plt.imshow(crop.crop((1200,1000,1900,1600))) plt.axis('off') (-0.5, 699.5, 599.5, -0.5)
pythonplt.figure(figsize=(4,4)) plt.imshow(crop.crop((1100,1200,1900,1800))) plt.axis('off') (-0.5, 799.5, 599.5, -0.5)
pythonplt.figure(figsize=(4,4)) plt.imshow(crop.crop((1400,1000,2300,1450))) plt.axis('off') (-0.5, 899.5, 449.5, -0.5)
python# let's detect luminance to approximate grey dots positions import cv2 gray = cv2.cvtColor(arr, cv2.COLOR_BGR2GRAY) # threshold to find small darkish points th = cv2.threshold(gray, 180, 255, cv2.THRESH_BINARY_INV)[1] # invert to find dark pixels # let's dilate small to get bigger kernel = np.ones((3,3), np.uint8) th2 = cv2.dilate(th, kernel, iterations=1) # find contours contours, _ = cv2.findContours(th2, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # filter contours which are small (points) maybe grey dots candidates = [] for cnt in contours: x,y,wc,hc = cv2.boundingRect(cnt) if wc<10 and hc<10: candidates.append((x,y)) # let's group by y approximate ys = [y for x,y in candidates] # cluster y by near equal spacing ys_sorted = sorted(ys) print(ys_sorted[:50])
python# show bottom left region plt.figure(figsize=(4,4)) plt.imshow(arr[1200:1700, 0:400]) plt.axis('off') (-0.5, 399.5, 499.5, -0.5)
pythonprint(arr.shape)
python# locate left axis x coordinate roughly # find columns with many dark pixels to find axis line gray = cv2.cvtColor(arr, cv2.COLOR_BGR2GRAY) # consider columns with many low intensity maybe cols_dark = [ (x, np.sum(gray[:,x]<50)) for x in range(arr.shape[1])] # Let's find peaks xs = sorted(cols_dark, key=lambda t: t[1], reverse=True)[:10] xs [(1072, 64), (1070, 62), (1071, 62), (1069, 61), (1093, 59), (1094, 59), (1241, 58), (2080, 56), (634, 54), (480, 53)]
pythonplt.figure(figsize=(4,4)) plt.imshow(crop.crop((1700,800,2400,1450))) plt.axis('off') (-0.5, 699.5, 649.5, -0.5)
pythonplt.figure(figsize=(4,4)) plt.imshow(crop.crop((1200,900,1900,1250))) plt.axis('off') (-0.5, 699.5, 349.5, -0.5)
pythonplt.figure(figsize=(4,4)) plt.imshow(crop.crop((1200,1100,1900,1500))) plt.axis('off') (-0.5, 699.5, 399.5, -0.5)
pythonplt.figure(figsize=(4,4)) plt.imshow(arr[1000:1400, 1000:2000]) plt.axis('off') (-0.5, 999.5, 399.5, -0.5)
pythonplt.figure(figsize=(4,4)) plt.imshow(arr[1000:1400, 800:1200]) plt.axis('off') (-0.5, 399.5, 399.5, -0.5)
pythonplt.figure(figsize=(4,4)) plt.imshow(arr[600:950, 350:1250]) plt.axis('off') (-0.5, 899.5, 349.5, -0.5)
pythonplt.figure(figsize=(4,4)) plt.imshow(arr[600:950, 200:450]) plt.axis('off') (-0.5, 249.5, 349.5, -0.5)
pythonplt.figure(figsize=(6,4)) plt.imshow(arr[500:900, 0:600]) plt.axis('off') (-0.5, 599.5, 399.5, -0.5)
pythonplt.figure(figsize=(4,4)) plt.imshow(arr[1000:1300, 300:800]) plt.axis('off') (-0.5, 499.5, 299.5, -0.5)
pythonplt.figure(figsize=(4,4)) plt.imshow(arr[900:1200, 550:850]) plt.axis('off') (-0.5, 299.5, 299.5, -0.5)
pythonplt.figure(figsize=(4,4)) plt.imshow(arr[800:1100, 1350:1650]) plt.axis('off') (-0.5, 299.5, 299.5, -0.5)
pythonplt.figure(figsize=(4,4)) plt.imshow(arr[1100:1400, 1300:2000]) plt.axis('off') (-0.5, 699.5, 299.5, -0.5)
pythonplt.figure(figsize=(4,4)) plt.imshow(arr[1100:1400, 1000:1400]) plt.axis('off') (-0.5, 399.5, 299.5, -0.5)
pythonplt.figure(figsize=(4,4)) plt.imshow(arr[1200:1550, 800:1500]) plt.axis('off') (-0.5, 699.5, 349.5, -0.5)
pythonplt.figure(figsize=(4,4)) plt.imshow(arr[900:1150, 1000:1400]) plt.axis('off') (-0.5, 399.5, 249.5, -0.5)
pythonplt.imshow(arr[1100:1350, 1850:2300]) plt.axis('off') (-0.5, 449.5, 249.5, -0.5)
pythonplt.figure(figsize=(4,4)) plt.imshow(arr[900:1150, 1600:2000]) plt.axis('off') (-0.5, 399.5, 249.5, -0.5)
python# detect greenish pixels in arr (RGB) mask_green = (arr[:,:,1] > 130) & (arr[:,:,0] < 150) & (arr[:,:,2] < 150) # morphological close to fill triangle interior maybe expand mask_green = cv2.dilate(mask_green.astype(np.uint8)*255, np.ones((5,5), np.uint8), iterations=3) # find contours contours, _ = cv2.findContours(mask_green, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) centers = [] for cnt in contours: x,y,w,h = cv2.boundingRect(cnt) if w>20 and h>20: cx, cy = x + w//2, y + h//2 centers.append((cx,cy)) # print centers print(len(centers)) print(sorted(centers, key=lambda p: p[0]))
pythonimport math, itertools, collections # define training data training = [ ((8,3),0), ((9,2),0), ((2,3),1), ((4,3),1), ((5,3),1), ((6,0),2), ((7,0),2), ((7,-1),2), ((8,-1),2), ((1,2),3), ((2,1),3), ((2,0),3), ((4,2),3), ((4,1),3), ((6,1),3) ] tests = [ ((3,4),1), ((8,2),0), ((5,0),2) ] def classify(point,k): x,y = point dists = [] for (px,py),cl in training: dist = math.hypot(px-x, py-y) dists.append((dist, cl, (px,py))) # sort by dist then class number dists.sort(key=lambda t: (t[0], t[1])) neighbors = dists[:k] counts=collections.Counter([cl for _,cl,_ in neighbors]) maxfreq = max(counts.values()) tied_classes = [cl for cl,cnt in counts.items() if cnt==maxfreq] if len(tied_classes)==1: return tied_classes[0] # tie: choose class with smaller sum distances sums = {cl: sum(dist for dist,cl2,_ in neighbors if cl2==cl) for cl in tied_classes} minsum = min(sums.values()) mins = [cl for cl,s in sums.items() if s==minsum] if len(mins)==1: return mins[0] # still tie: choose smaller class number return min(mins) valid_k=[] for k in range(1,16): ok=True for (pt,truth) in tests: pred=classify(pt,k) if pred!=truth: ok=False break if ok: valid_k.append(k) valid_k [1, 2, 5]
pythonfor k in range(1,16): preds=[classify(pt,k) for pt,_ in tests] print(k,preds)
Решение
В таблицах ниже указаны 15 обучающих точек (три контрольные - (8, 2), (3, 4), (5, 0) – заранее убраны)
и рассчитаны расстояния от каждой из них до этих трёх контрольных точек.
| № | Коорд-ты | Класс |
|---|---|---|
| 1 | (8, 3) | 0 |
| 2 | (9, 2) | 0 |
| 3 | (2, 3) | 1 |
| 4 | (4, 3) | 1 |
| 5 | (5, 3) | 1 |
| 6 | (6, 0) | 2 |
| 7 | (7, 0) | 2 |
| 8 | (7, -1) | 2 |
| 9 | (8, -1) | 2 |
| 10 | (1, 2) | 3 |
| 11 | (2, 1) | 3 |
| 12 | (2, 0) | 3 |
| 13 | (4, 2) | 3 |
| 14 | (4, 1) | 3 |
| 15 | (6, 1) | 3 |
Ближайшие точки по возрастанию расстояния
| r | координаты | класс |
|---|---|---|
| √2 | (2, 3) | 1 |
| √2 | (4, 3) | 1 |
| √5 | (5, 3) | 1 |
| … | … | … |
Большинство среди первых k соседей будет класс 1 при любом k ≤ 5
(дальние объекты не успевают набрать голосов).
Начиная с k ≥ 6 голосов у классов 1 и 3 становится поровну;
правило «меньшая сумма расстояний» оставляет 1 только до k = 6,
а при k ≥ 7 побеждает 3.
| r | координаты | класс |
|---|---|---|
| 1 | (8, 3) | 0 |
| 1 | (9, 2) | 0 |
| √2 | (8, 1) — отсутствует | |
| … | … | … |
Первые два ближайших объекта уже дают большинство классу 0;
ни при каком k класс 0 больше не уступает, пока k ≤ 5.
При k = 6 и 7 появляются четыре зелёных треугольника ⇒
частота классов 0 и 2 равна 2×2,
но сумма расстояний у красных меньше ⇒ выбирается 0.
Начиная с k = 8 красных уже недостаточно и метод выдаёт 2, затем 3.
| r | координаты | класс |
|---|---|---|
| 1 | (6, 0) | 2 |
| √2 | (4, 1) | 3 |
| √2 | (6, 1) | 3 |
| 2 | (7, 0) | 2 |
| √5 | (7, -1) | 2 |
| … | … | … |
Метод k-ближайших соседей правильно определяет все три контрольные точки только при
Для остальных значений k хотя бы одна из трёх точек классифицируется неверно.