চিত্রটিতে একাধিক আয়তক্ষেত্র সনাক্ত করুন


13

আমি এই ছবিতে পাইপের গণনা সনাক্ত করার চেষ্টা করছি। এর জন্য, আমি ওপেনসিভি এবং পাইথন-ভিত্তিক সনাক্তকরণ ব্যবহার করছি। অনুরূপ প্রশ্নের বিদ্যমান উত্তরগুলির ভিত্তিতে, আমি নিম্নলিখিত পদক্ষেপগুলি নিয়ে আসতে সক্ষম হয়েছি

  1. ছবিটি খুলুন
  2. এটি ফিল্টার করুন
  3. এজ সনাক্তকরণ প্রয়োগ করুন
  4. ব্যবহার করুন
  5. গণনা পরীক্ষা করুন

এখানে চিত্র বর্ণনা লিখুন

পাইপগুলির মোট গণনা ~ 909 হয় যখন আমরা এটি ম্যানুয়ালি গণনা করি বা 4 নিই।

ফিল্টার প্রয়োগের পরে

import cv2
import matplotlib.pyplot as plt
import numpy as np

img = cv2.imread('images/input-rectpipe-1.jpg')
blur_hor = cv2.filter2D(img[:, :, 0], cv2.CV_32F, kernel=np.ones((11,1,1), np.float32)/11.0, borderType=cv2.BORDER_CONSTANT)
blur_vert = cv2.filter2D(img[:, :, 0], cv2.CV_32F, kernel=np.ones((1,11,1), np.float32)/11.0, borderType=cv2.BORDER_CONSTANT)
mask = ((img[:,:,0]>blur_hor*1.2) | (img[:,:,0]>blur_vert*1.2)).astype(np.uint8)*255

আমি এই মুখোশযুক্ত ছবি পেতে

এখানে চিত্র বর্ণনা লিখুন

এটি প্রদর্শিত হওয়া আয়তক্ষেত্রগুলির সংখ্যার দিক থেকে এটি মোটামুটি নির্ভুল দেখাচ্ছে। যাইহোক, যখন আমি গণনাটি নেওয়ার চেষ্টা করি এবং ছবির উপরে বাউন্ডিং বক্সটি প্লট করি তখন এটি অনেকগুলি অযাচিত অঞ্চলগুলিকেও পছন্দ করে। চেনাশোনাগুলির জন্য, HoughCircles সর্বাধিক এবং ন্যূনতম ব্যাসার্ধ নির্ধারণ করার একটি উপায় রয়েছে। আয়তক্ষেত্রগুলির জন্য কি অনুরূপ কিছু রয়েছে যা নির্ভুলতার উন্নতি করতে পারে। এছাড়াও, আমি এই সমস্যার বিকল্প পদ্ধতির পরামর্শের জন্য উন্মুক্ত।

ret,thresh = cv2.threshold(mask,127,255,0)
contours,hierarchy = cv2.findContours(thresh, 1, 2)

count = 0

for i in range(len(contours)):

  count = count+1
  x,y,w,h = cv2.boundingRect(contours[i]) 
  rect = cv2.minAreaRect(contours[i])
  area = cv2.contourArea(contours[i])
  box = cv2.boxPoints(rect)
  ratio = w/h
  M = cv2.moments(contours[i])

  if M["m00"] == 0.0:
         cX = int(M["m10"] / 1 )
         cY = int(M["m01"] / 1 )

  if M["m00"] != 0.0:
    cX = int(M["m10"] / M["m00"])
    cY = int(M["m01"] / M["m00"])

  if (area > 50 and area < 220 and hierarchy[0][i][2] < 0 and (ratio > .5 and ratio < 2)):
    #cv2.rectangle(img, (x,y), (x+w,y+h), (0,255,0), 2)
    cv2.circle(img, (cX, cY), 1, (255, 255, 255), -1)
    count = count + 1 



print(count)

cv2.imshow("m",mask)
cv2.imshow("f",img)
cv2.waitKey(0)

এখানে চিত্র বর্ণনা লিখুন

আপডেট দ্বিতীয় উত্তরের ভিত্তিতে আমি সি ++ কোডটিকে পাইথন কোডে রূপান্তর করেছি এবং নিকটতর ফলাফল পেয়েছি তবে এখনও কয়েকটি সুস্পষ্ট আয়তক্ষেত্র মিস করছি।

এখানে চিত্র বর্ণনা লিখুন


আপনার উন্মাদ চিত্রটিতে, একটি দ্বৈত ক্রিয়াকলাপ তৈরি করুন। তারপরে কেবলমাত্র অভ্যন্তরীণ দিকগুলি সনাক্ত করুন (প্রথম স্তর)।
মিক্কা

আপনি কি আপনার মাস্ক চিত্রটি পিএনজি হিসাবে সরবরাহ করতে পারেন?
মিক্কা

1
আমি png সংস্করণ দিয়ে প্রশ্নটি আপডেট করেছি
ডোনি

কয়টি পাইপ সনাক্ত করা উচিত সে সম্পর্কে আপনার কি কোনও স্থল সত্য রয়েছে ?
টিএ

একটি জিনিস যা আপনি চেষ্টা করতে পারেন তা অনুপস্থিত সনাক্তকরণগুলির উন্নতির জন্য চৌম্বকীয় ধাপটি টিউন করা যেতে পারে। ওৎসুর প্রান্তিক বা অভিযোজিত প্রান্তিকের দিকে নজর দিন। যাইহোক, আপনার বর্তমান সমাধানটি সম্ভবত আপনি সেরা .তিহ্যগত চিত্র প্রক্রিয়াকরণ কৌশলগুলি ব্যবহার করতে যাচ্ছেন। অন্যথায় আপনি গভীর / মেশিন লার্নিং
25

উত্তর:


6

অবশ্যই আপনি তাদের এলাকা দিয়ে ফিল্টার করতে পারে। আমি আপনার বাইনারি চিত্র নিয়েছি এবং নীচের মত কাজ চালিয়েছি:

1- ফাইন্ডকন্টরস থেকে আপনি যে সমস্ত রূপক খুঁজে পেয়েছেন তার একটি লুপ করুন

2- প্রতিটি কনট্যুরটি লুপ চেক-এ একটি অভ্যন্তরীণ কনট্যুর কিনা or

3- যা অভ্যন্তরীণ রূপকগুলি থেকে তাদের ক্ষেত্রটি পরীক্ষা করুন এবং যদি ক্ষেত্রটি গ্রহণযোগ্য সীমার মধ্যে থাকে তবে প্রতিটি কনট্যুরের প্রস্থ / উচ্চতার অনুপাতটি পরীক্ষা করুন এবং শেষ পর্যন্ত যদি এটি খুব ভাল হয় তবে সেই কনট্যুরটিকে পাইপ হিসাবে গণনা করুন।

আমি আপনার বাইনারি ছবিতে উপরোক্ত পদ্ধতিটি করেছি এবং 794 টি পাইপ পেয়েছি :

এখানে চিত্র বর্ণনা লিখুন

(কিছু বাক্স হারিয়ে গেছে যদিও, আপনার ছবিতে আরও পৃথকযোগ্য বাক্সগুলি পেতে প্রান্ত ডিটেক্টরের প্যারামিটারগুলি পরিবর্তন করা উচিত))

এবং এখানে কোডটি রয়েছে (এটি সি ++ তবে সহজেই অজগরে রূপান্তরযোগ্য):

Mat img__1, img__2,img__ = imread("E:/R.jpg", 0);

threshold(img__, img__1, 128, 255, THRESH_BINARY);

vector<vector<Point>> contours;
vector< Vec4i > hierarchy;

findContours(img__1, contours, hierarchy, RETR_CCOMP, CHAIN_APPROX_NONE);

Mat tmp = Mat::zeros(img__1.size(), CV_8U);
int k = 0;
for (size_t i = 0; i < contours.size(); i++)
{
    double area = contourArea(contours[i]);
    Rect rec = boundingRect(contours[i]);
    float ratio = rec.width / float(rec.height);

    if (area > 50 && area < 220 && hierarchy[i][2]<0 && (ratio > .5 && ratio < 2) ) # hierarchy[i][2]<0 stands for internal contours
    {
        k++;
        drawContours(tmp, contours, i, Scalar(255, 255, 255), -1);
    }
}
cout << "k= " << k << "\n";
imshow("1", img__1); 
imshow("2", tmp);
waitKey(0);

2

এই সমস্যাটি সমাধান করার জন্য অনেকগুলি পদ্ধতি রয়েছে তবে আমি সন্দেহ করি যে কোনও ধরণের অ্যাড-হডের ব্যবস্থা ছাড়াই একটি পদ্ধতি থাকবে। এই সমস্যার আরেকটি প্রচেষ্টা এখানে।

প্রান্তের তথ্য ব্যবহারের পরিবর্তে, আমি একটি এলবিপি (স্থানীয় বাইনারি প্যাটার্ন) -র মতো ফিল্টারটি প্রস্তাব করি যা পার্শ্ববর্তী পিক্সেলটিকে কেন্দ্রের মানের সাথে তুলনা করে। আশেপাশের পিক্সেলের একটি নির্দিষ্ট শতাংশ যদি কেন্দ্রের পিক্সেলের চেয়ে বড় হয় তবে সেন্টার পিক্সেলটি 255 লেবেলযুক্ত হবে the

এই তীব্রতা ভিত্তিক পদ্ধতিটি এই ধারনাতে চালিত হয় যে পাইপ কেন্দ্রটি সর্বদা পাইপের প্রান্তগুলির চেয়ে অন্ধকার থাকে। যেহেতু এটি তীব্রতার সাথে তুলনা করছে তাই এটি যতক্ষণ না কিছু বৈপরীত্য থেকে যায় ততক্ষণ ভালভাবে কাজ করা উচিত।

এই প্রক্রিয়াটির মাধ্যমে, আপনি প্রতিটি পাইপ এবং কিছু শোরগোলের জন্য বাইনারি ব্লব সহ একটি চিত্র পাবেন। আপনাকে তাদের কিছু পূর্ব-পরিচিত শর্তের সাথে সরাতে হবে যেমন আকার, আকার, ফিল_রেটিও, রঙ এবং ইত্যাদি শর্তটি প্রদত্ত কোডটিতে পাওয়া যেতে পারে।

import cv2
import matplotlib.pyplot as plt
import numpy as np

# Morphological function sets
def morph_operation(matinput):
  kernel =  cv2.getStructuringElement(cv2.MORPH_CROSS,(3,3))

  morph = cv2.erode(matinput,kernel,iterations=1)
  morph = cv2.dilate(morph,kernel,iterations=2)
  morph = cv2.erode(matinput,kernel,iterations=1)
  morph = cv2.dilate(morph,kernel,iterations=1)

  return morph


# Analyze blobs
def analyze_blob(matblobs,display_frame):

  _,blobs,_ = cv2.findContours(matblobs,cv2.RETR_LIST ,cv2.CHAIN_APPROX_SIMPLE)
  valid_blobs = []

  for i,blob in enumerate(blobs):
    rot_rect = cv2.minAreaRect(blob)
    b_rect = cv2.boundingRect(blob)


    (cx,cy),(sw,sh),angle = rot_rect
    rx,ry,rw,rh = b_rect

    box = cv2.boxPoints(rot_rect)
    box = np.int0(box)

    # Draw the segmented Box region
    frame = cv2.drawContours(display_frame,[box],0,(0,0,255),1)

    on_count = cv2.contourArea(blob)
    total_count = sw*sh
    if total_count <= 0:
      continue

    if sh > sw :
      temp = sw
      sw = sh
      sh = temp

    # minimum area
    if sw * sh < 20:
      continue

    # maximum area
    if sw * sh > 100:
      continue  

    # ratio of box
    rect_ratio = sw / sh
    if rect_ratio <= 1 or rect_ratio >= 3.5:
      continue

    # ratio of fill  
    fill_ratio = on_count / total_count
    if fill_ratio < 0.4 :
      continue

    # remove blob that is too bright
    if display_frame[int(cy),int(cx),0] > 75:
      continue


    valid_blobs.append(blob)

  if valid_blobs:
    print("Number of Blobs : " ,len(valid_blobs))
  cv2.imshow("display_frame_in",display_frame)

  return valid_blobs

def lbp_like_method(matinput,radius,stren,off):

  height, width = np.shape(matinput)

  roi_radius = radius
  peri = roi_radius * 8
  matdst = np.zeros_like(matinput)
  for y in range(height):
    y_ = y - roi_radius
    _y = y + roi_radius
    if y_ < 0 or _y >= height:
      continue


    for x in range(width):
      x_ = x - roi_radius
      _x = x + roi_radius
      if x_ < 0 or _x >= width:
        continue

      r1 = matinput[y_:_y,x_]
      r2 = matinput[y_:_y,_x]
      r3 = matinput[y_,x_:_x]
      r4 = matinput[_y,x_:_x]

      center = matinput[y,x]
      valid_cell_1 = len(r1[r1 > center + off])
      valid_cell_2 = len(r2[r2 > center + off])
      valid_cell_3 = len(r3[r3 > center + off])
      valid_cell_4 = len(r4[r4 > center + off])

      total = valid_cell_1 + valid_cell_2 + valid_cell_3 + valid_cell_4

      if total > stren * peri:
        matdst[y,x] = 255

  return matdst


def main_process():

  img = cv2.imread('image.jpg')    
  gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)



  # Blured to remove noise 
  blurred = cv2.GaussianBlur(gray,(3,3),-1)

  # Parameter tuning
  winsize = 5
  peri = 0.6
  off = 4

  matlbp = lbp_like_method(gray,winsize,peri,off)
  cv2.imshow("matlbp",matlbp)
  cv2.waitKey(1)

  matmorph = morph_operation(matlbp)
  cv2.imshow("matmorph",matmorph)
  cv2.waitKey(1)


  display_color = cv2.cvtColor(gray,cv2.COLOR_GRAY2BGR)
  valid_blobs = analyze_blob(matmorph,display_color)


  for b in range(len(valid_blobs)):
    cv2.drawContours(display_color,valid_blobs,b,(0,255,255),-1)


  cv2.imshow("display_color",display_color)
  cv2.waitKey(0)


if __name__ == '__main__':
  main_process()

এলবিপি-এর মতো প্রক্রিয়াজাতকরণ থেকে ফলাফল এখানে চিত্র বর্ণনা লিখুন

রূপচর্চা প্রক্রিয়া দিয়ে পরিষ্কার করার পরে এখানে চিত্র বর্ণনা লিখুন

সমস্ত ব্লব প্রার্থী এবং হলুদ বিভাগগুলিতে ব্লবগুলি দেখানো রয়েছে যা আমরা নির্ধারিত সমস্ত শর্তকে পাশ দিয়ে দেখায় boxes পাইপের বান্ডেলের নীচে এবং উপরে কিছু মিথ্যা অ্যালার্ম রয়েছে তবে সেগুলি কিছু সীমানা শর্তের সাথে বাদ দেওয়া যেতে পারে। এখানে চিত্র বর্ণনা লিখুন

মোট পাইপ পাওয়া গেছে: 943


কোডটি চালানোর সময় আমি এই ত্রুটিটি পেয়েছি, _ = cv2.findContours (matblobs, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) মান মূল্য: আনপ্যাক করার জন্য পর্যাপ্ত মান নেই (প্রত্যাশিত 3, পেয়েছে 2)
ডনি

আপনি অবশ্যই ওপেনসিভির একটি আলাদা সংস্করণ ব্যবহার করছেন। আপনাকে যা করতে হবে তা হ'ল প্রথম কোডটিকে "_" ফাংশন থেকে প্রাপ্ত করার জন্য মূল কোড থেকে সরিয়ে ফেলতে হবে। ব্লবস, _ = cv2.findContours (ম্যাটব্লবস, সিভি 2.আরটিআর_লিস্ট, সিভি 2.সিএইচএএপিএপিআরএক্সআরএমএসআইএমপিএল)
ইয়াপবউ ৮87
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.