質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Q&A

0回答

666閲覧

画像処理で出るエラーへの対応方法(配列の次元数の問題?)

pst

総合スコア0

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

0グッド

0クリップ

投稿2022/01/15 07:30

下記のプログラムに画像を通した際にエラーコードを吐くのですが解決方法を知りたいです。
画像はデジカメで撮ったものを縮小しています

#縮小 import cv2 import numpy as np import os from PIL import Image dir_name = "sy" new_dir_name = "sy2" files = os.listdir(dir_name) for file in files: photo = Image.open(os.path.join(dir_name, file)) photo_resize = photo.resize((img.width // 5, img.height // 5)) photo_resize.save(os.path.join(new_dir_name, file))

エラーコード
<ipython-input-54-6f0e5c8ccf17> in resultImage(img, res, tobjy, tobjh)
260 sy = tobjy - 20;sh = tobjh + 30;hh = h + 20
261 res_disp = np.full((hh, w, 3), (255,255,255), np.uint8)
--> 262 res_disp[0:sh, 0:w] = img[sy:sy+sh]
263 res_disp[hh//2:hh//2+sh, 0:w] = res[sy:sy+sh]
264 cv2.imwrite(newdirname, res_disp)

ValueError: could not broadcast input array from shape (20,336,3) into shape (138,336,3)

import cv2 import math import numpy as np import openpyxl import os from PIL import Image dir_name = "sy2/30.jpg" newdirname = "sy3/30.jpg" class WidthScanner: def __init__(self, coef, mx, my): self._imx = int(mx) self._imy = int(my) self.delta = -1 / coef[0] self.b = my - mx * self.delta def getX(self, y): x = (y - self.b) / self.delta return x def getPoints(self, binimg): print(binimg.shape) h,w = binimg.shape # 中央線より上をスキャン x1 = 0 y1 = 0 for y in range(self._imy, 0, -1): x = int(self.getX(y)) print(binimg[y,x]) if binimg[y,x] == 0: break else: x1 = x y1 = y # 中央線より下をスキャン x2 = 0 y2 = 0 for y in range(self._imy, h, 1): x = int(self.getX(y)) if binimg[y,x] == 0: break else: x2 = x y2 = y dist = math.sqrt((x1-x2)**2+(y1-y2)**2) return (x1,y1), (x2, y2), dist # イメージロードし、カラー、グレイスケール、二値画像 # 返却値 : カラー(img),グレイスケール(gray),二値画像(bw) def supplyImage(imageFile): img = cv2.imread(imageFile, cv2.IMREAD_COLOR) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) gray = cv2.medianBlur(gray, 5) _, bw = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU) bw = cv2.bitwise_not(bw) # モルフォロジー変換 kernel5x5 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5)) bw = cv2.morphologyEx(bw, cv2.MORPH_CLOSE, kernel5x5, iterations=5) return img, gray, bw def main(): #ブックを開く book = openpyxl.load_workbook('test/test.xlsx') book.create_sheet(index=0, title='ニンジン') # シートを取得 sheet = book['ニンジン'] # セルへ書き込む sheet['A1'] = 'ナンバー' sheet['B1'] ='ピクセル数' # イメージ供給 img, gray, bw = supplyImage(dir_name) # ラベリング target_lb_id = 1 nLabels, labelImages, data, center = cv2.connectedComponentsWithStats(bw) tobjx = data[target_lb_id, 0] tobjy = data[target_lb_id, 1] tobjw = data[target_lb_id, 2] tobjh = data[target_lb_id, 3] tarea = data[target_lb_id, 4] h, w = img.shape[:2] bres = np.zeros((h, w), np.uint8) bres_cl = np.zeros((h, w, 3), np.uint8) bres[labelImages == target_lb_id] = 255 img_mrg = cv2.merge((bres,bres,bres)) res = cv2.bitwise_and(img,cv2.merge((bres,bres,bres)) ) # 輪郭取得 contours, _ = cv2.findContours(bres, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) for i, cnt in enumerate(contours): cv2.drawContours(res,[cnt],0,(0,0,255),1) ypts, xpts = np.where(bres == 255) rv = np.polyfit(xpts ,ypts, 3) expr = np.poly1d(rv) # プロジェクション projectionPCA(xpts, ypts) # 枠を描画 cv2.rectangle(res,(tobjx,tobjy),(tobjx+tobjw,tobjy+tobjh),(0,255,255),1) # 幅を測る offsetx = 10;incx = 16;lbno = 1 cary = np.zeros((incx,), np.float32) carx = np.zeros((incx,), np.float32) for sx in range(tobjx+incx, tobjx+tobjw-incx, incx): cary = np.zeros((incx,), np.uint8) for x in range(sx, sx+incx): vy = expr(x) carx[sx-x] = x cary[sx-x] = vy rv1 = np.polyfit(carx ,cary,1) expr1 = np.poly1d(rv1) # スキャンセグメントの中間座標 mx = sx + incx // 2 my = expr(mx) # 直行を求める ex = WidthScanner(rv1, mx, my) spt, ept, dist = ex.getPoints(bw) cv2.line(res, (int(spt[0]), int(spt[1])), (int(ept[0]), int(ept[1])), (255,0,0), 1, lineType=cv2.LINE_AA) cv2.putText(res, str(lbno), (int(spt[0]-6), int(spt[1])-8), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0,255,255), 1,cv2.LINE_AA) print('%2d.直径 %.2f' % (lbno, dist)) # シートを取得 sheet = book['ニンジン'] # セルへ書き込む sheet.cell(row=lbno+2,column=1).value = lbno sheet.cell(row=lbno+2,column=2).value = dist # 保存する book.save('test/test.xlsx') lbno += 1 # 長さを測る total_len = 0 scan_flag = False by = 0 for x in range(tobjx, tobjx+tobjw): if scan_flag == False and bw[int(vy), x] == 255: scan_flag = True vy = expr(x) bx = x by = vy elif scan_flag == True : if bw[int(vy), x] == 255: vy = expr(x) sdist = math.sqrt((bx - x)** 2 + (by - vy) ** 2) total_len += sdist # 3次回帰曲線を描画 cv2.line(res, (int(x), int(vy)), (int(bx), int(by)), (255,0,255), 2, lineType=cv2.LINE_AA) bx = x by = vy else: break print('トータル長(pixel)=%.2f' %(total_len)) # シートを取得 sheet = book['ニンジン'] # セルへ書き込む sheet['C1'] = 'トータル長' sheet['D1'] = total_len # 保存する book.save('test/test.xlsx') #------------------------- # 曲がり具合を調べる # 最小・最大を求める minx = 9999999 maxx = -9999999 miny = 9999999 maxy = -9999999 for x in range(tobjx, tobjx+tobjw): vy = expr(x) miny = min(miny, vy) maxy = max(miny, vy) # 最大を求める miny = 9999999 for x in range(tobjx, tobjx+tobjw): vy = expr(x) miny = min(miny, vy) res_disp = resultImage(img, res, tobjy, tobjh) cv2.imshow("res_disp", res_disp) cv2.waitKey(0) #曲がり具合計測 def projectionPCA(xpts, ypts): data_pts = np.empty((xpts.shape[0], 2), dtype=np.float64) data_pts[:,0] = xpts data_pts[:,1] = ypts # 主成分分析 # mean : 投影前に差し引かれ、逆投影後に追加された平均値 # eigenvalues : 共変動行列の固有値 # eigenvectors : 共変動行列の固有ベクトル mean = np.empty((0)) mean, eigenvectors, eigenvalues = cv2.PCACompute2(data_pts, mean) # PCA投影(プロジェクション) compressed_data = cv2.PCAProject(data_pts, mean, eigenvectors) rv = np.polyfit(compressed_data[:,0],compressed_data[:,1], 3) expr = np.poly1d(rv) maxx = np.max(compressed_data[:,0]) minx = np.min(compressed_data[:,0]) maxy = np.max(compressed_data[:,1]) miny = np.min(compressed_data[:,1]) difval = [] for x in range(int(minx), int(maxx)+1): vy = expr(x) difval.append(vy) if getSigned(difval[0]) == 1 and getSigned(difval[-1]) == 1: # 両端が+の場合 val1 = abs(np.min(difval)) val2 = abs(difval[0]) + abs(difval[-1]) elif getSigned(difval[0]) == -1 and getSigned(difval[-1]) == -1: # 両端が-の場合 val1 = np.max(difval) val2 = abs(difval[0]) + abs(difval[-1]) else: val1 = abs(np.min(difval)) val2 = abs(np.max(difval)) val = val1 + val2 print('曲がり具合 長さ(pixel):', val) #ブックを開く book = openpyxl.load_workbook('test/test.xlsx') # シートを取得 sheet = book['ニンジン'] # セルへ書き込む sheet['E1'] = '曲がり具合 長さ' sheet['F1'] = val # 保存する book.save('test/test.xlsx') # 値の付合を求める. 1:+, -1:- def getSigned(val): if val < 0: return -1 else: return 1 def resultImage(img, res, tobjy, tobjh): h, w = img.shape[:2] sy = tobjy - 20;sh = tobjh + 30;hh = h + 20 res_disp = np.full((hh, w, 3), (255,255,255), np.uint8) res_disp[0:sh, 0:w] = img[sy:sy+sh] res_disp[hh//2:hh//2+sh, 0:w] = res[sy:sy+sh] cv2.imwrite(newdirname, res_disp) cv2.imshow('test', res_disp) cv2.waitKey() cv2.destroyAllWindows() if __name__ == '__main__': main()

画像は以下のものになります

イメージ説明

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

melian

2022/01/15 08:02

エラーが発生する原因は、 res_disp[0:sh, 0:w] = img[sy:sy+sh] の部分で sy の値が負値になる場合があるからです。
pst

2022/01/16 07:16

ありがとうございます。 対応方法としてはどのようにすればいいでしょうか?
melian

2022/01/16 10:51

sy が負値になる原因をきちんと調べる方が良いかと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問