@ALL これは、元の質問を編集して、主題をもう少し明らかにしたものです。
問題文
- 産業用 P&ID プロットがあるとします。
- 工程に重要な一部の線のみを着色することを目指しています。
- ユーザーは線分をクリック (マウスの左クリック) するだけで、線分に色を付けることができます。
問題アプローチ
私はプログラミングが初めてです-> Python(3.5)を使用してこれを試してください。私の見方では、アルゴリズムは次のようになります。
- プロットは .pdf 形式になります。したがって、この例で示されているように、PIL ImageGrab を使用するか、.pdf を .png に変換できます。
- アルゴリズムは、マウス クリックの周囲のピクセルを検索し、それを同じサイズの別の部分 (たとえば 6x3 ピクセルのストリップ) と比較しますが、左/右に 1 ステップ (1 ~ 5 ピクセル)
- それらの差の平均を確認すると、2 つのストリップが同一であるかどうかがわかります。
- このようにして、アルゴリズムは行末、矢印、角、またはその他の要素の両方を見つける必要があります
- これが検出され、位置が記録され、マークアップ線が描画されると、ユーザーは別の線を選択することが期待されます
要約する
- 必要な行をクリックします
- マウス クリックの周囲の画像の小さな部分をつかみます
- 線が水平か垂直かを確認する
- 指定されたサイズの水平/垂直スライスをトリミングします
- 改行を見つけて、改行の位置を記録する
- 見つかった 2 つの位置の間に、特定の色 (緑としましょう) の線を引きます。
- 次の行が選択されるのを待ってから繰り返します
他の考え
- 添付のサンプル画像の 2 つの写真と、私が達成しようとしていることを見つけることができます。
- ここにあるアプローチを使用して、スライスの「穴」を見つけようとしました: OpenCV to find line Ends
- ImageGrab ルーチンなどに固執する厳密なルールはありません。
- 私が使用できる他の戦術を知っている場合は、お気軽にコメントしてください
- どんなアドバイスでも大歓迎です。
サンプル画像:
望ましい結果 (ペイントで変更):
これまでに試した作業で投稿に更新を追加する
元のコードにいくつかの変更を加えたので、以下に投稿します。コメント内のすべては、デバッグまたは説明用です。あなたの助けは大歓迎です! 介入することを恐れないでください。
import win32gui as w
from PIL import ImageStat, ImageChops, Image, ImageDraw
import win32api as wa
img=Image.open("Trials.jpg")
img_width=img.size[0]
img_height=img.size[1]
#Using 1920 x 1080 resolution
#Hide the taskbar to center the Photo Viewer
#Defining a way to make sure the mouse click is inside the image
#Substract the width from total and divide by 2 to get base point of the crop
width_lim = (1920 - img_width)/2
height_lim = (1080 - img_height)/2-7
#After several tests, the math in calculating the height is off by 7 pixels, hence the correction
#Use these values when doing the crop
#Check if left mouse button was pressed and record its position
left_p = wa.GetKeyState(0x01)
#print(left_p)
while True :
a=wa.GetKeyState(0x01)
if a != left_p:
left_p = a
if a<0 :
pos = w.GetCursorPos()
pos_x=pos[0]-width_lim
pos_y=pos[1]-height_lim
# print(pos_x,pos_y)
else:
break
#img.show()
#print(img.size)
#Define the crop height; size is doubled
height_size = 10
#Define max length limit
#Getting a horizontal strip
im_hor = img.crop(box=[0, pos_y-height_size, img_width, pos_y+height_size])
#im_hor.show()
#failed in trying crop a small square of 3x3 size using the pos_x
#sq_size = 3
#st_sq = im_hor.crop(box=[pos_x,0,pos_x+sq_size,height_size*2])
#st_sq.show()
#going back to the code it works
#crop a standard strip and compare with a new test one
#if the mean of difference is zero, the strips are identical
#still looking for a way to find the position of the central pixel (that would be the one with maximum value - black)
strip_len = 3
step = 3
i = pos_x
st_sq = im_hor.crop(box=[i,0,i+strip_len,height_size*2])
test_sq = im_hor.crop(box=[i+step,0,i+strip_len+step,height_size*2])
diff = ImageChops.difference(st_sq,test_sq)
stat=ImageStat.Stat(diff)
mean = stat.mean
mean1 = stat.mean
#print(mean)
#iterate to the right until finding a different strip, record position
while mean==[0,0,0]:
i = i+1
st_sq = im_hor.crop(box=[i,0,i+strip_len,height_size*2])
#st_sq.show()
test_sq = im_hor.crop(box=[i+step,0,i+strip_len+step,height_size*2])
#test_sq.show()
diff = ImageChops.difference(st_sq,test_sq)
#diff.show()
stat=ImageStat.Stat(diff)
mean = stat.mean
# print(mean)
print(i-1)
r = i-1
#print("STOP")
#print(r)
#record the right end as r = i-1
#iterate to the left until finding a different strip. record the position
while mean1==[0,0,0]:
i = i-1
st_sq = im_hor.crop(box=[i,0,i+strip_len,height_size*2])
#st_sq.show()
test_sq = im_hor.crop(box=[i+step,0,i+strip_len+step,height_size*2])
#test_sq.show()
diff = ImageChops.difference(st_sq,test_sq)
#diff.show()
stat=ImageStat.Stat(diff)
mean1 = stat.mean
# print(mean)
#print("STOP")
print(i+1)
l = i+1
#record the left end as l=i+1
test_draw = ImageDraw.Draw(img)
test_draw.line([l,pos_y,r,pos_y], fill=128)
img.show()
#find another approach or die trying!!!
以下は私が得た結果です。それは私が望んでいたものではありませんが、正しい軌道に乗っているように感じます. ストリップ内のピクセル位置を見つけて、それを全体像のピクセル位置に相対的にするために、実際にいくつかの助けを借りることができました。
この種の別の画像は、より良い品質ですが、より多くの問題を争いにもたらします。