সুচিপত্র:

রোবটিক বিড বাছাই: 3 টি ধাপ (ছবি সহ)
রোবটিক বিড বাছাই: 3 টি ধাপ (ছবি সহ)

ভিডিও: রোবটিক বিড বাছাই: 3 টি ধাপ (ছবি সহ)

ভিডিও: রোবটিক বিড বাছাই: 3 টি ধাপ (ছবি সহ)
ভিডিও: ৬ষ্ঠ শ্রেণির জীবন ও জীবিকা বার্ষিক মূল্যায়ন উত্তর ২০২৩ | Class 6 Jibon o Jibika Annual Answer 2023 2024, নভেম্বর
Anonim
Image
Image
রোবোটিক পুঁতি সাজানো
রোবোটিক পুঁতি সাজানো
রোবোটিক পুঁতি সাজানো
রোবোটিক পুঁতি সাজানো
রোবোটিক পুঁতি সাজানো
রোবোটিক পুঁতি সাজানো

এই প্রকল্পে, আমরা রঙ দ্বারা পার্লার পুঁতি সাজানোর জন্য একটি রোবট তৈরি করব।

আমি সবসময় একটি রঙ বাছাই রোবট তৈরি করতে চেয়েছি, তাই যখন আমার মেয়ে পার্লার বিড ক্রাফটিংয়ে আগ্রহী হয়েছিল, আমি এটিকে একটি নিখুঁত সুযোগ হিসাবে দেখেছিলাম।

Perler জপমালা একটি পেগবোর্ডের উপর অনেক জপমালা স্থাপন করে, এবং তারপর একটি লোহা দিয়ে তাদের একসঙ্গে গলিয়ে ফিউজড আর্ট প্রকল্প তৈরি করতে ব্যবহৃত হয়। আপনি সাধারণত এই জপমালা দৈত্য 22, 000 পুঁতি মিশ্রিত রঙের প্যাকগুলিতে কিনে থাকেন এবং আপনার পছন্দসই রঙের সন্ধানে প্রচুর সময় ব্যয় করেন, তাই আমি ভেবেছিলাম এগুলি বাছাই করা শিল্প দক্ষতা বাড়িয়ে তুলবে।

আমি Phidgets Inc. এর জন্য কাজ করি তাই আমি এই প্রকল্পের জন্য বেশিরভাগ Phidgets ব্যবহার করেছি - কিন্তু এটি যে কোন উপযুক্ত হার্ডওয়্যার ব্যবহার করে করা যেতে পারে।

ধাপ 1: হার্ডওয়্যার

এখানে আমি এই নির্মাণ করতে ব্যবহৃত। আমি এটি phidgets.com এর অংশগুলি এবং বাড়ির চারপাশে পড়ে থাকা জিনিসগুলির সাথে 100% তৈরি করেছি।

Phidgets বোর্ড, মোটর, হার্ডওয়্যার

  • HUB0000 - VINT Hub Phidget
  • 1108 - চৌম্বকীয় সেন্সর
  • 2x STC1001 - 2.5A Stepper Phidget
  • 2x 3324 - 42STH38 NEMA -17 বাইপোলার গিয়ারলেস স্টেপার
  • 3x 3002 - ফিজেট কেবল 60 সেমি
  • 3403 - ইউএসবি 2.0 4 -পোর্ট হাব
  • 3031 - মহিলা পিগটেল 5.5x2.1 মিমি
  • 3029 - 2 তারের 100 'টুইস্টেড কেবল
  • 3604 - 10 মিমি সাদা LED (10 ব্যাগ)
  • 3402 - ইউএসবি ওয়েবক্যাম

অন্য অংশ গুলো

  • 24VDC 2.0A পাওয়ার সাপ্লাই
  • গ্যারেজ থেকে কাঠ এবং ধাতু স্ক্র্যাপ করুন
  • জিপ বন্ধন
  • প্লাস্টিকের পাত্রে নিচের অংশ কেটে দেওয়া হয়েছে

ধাপ 2: রোবট ডিজাইন করুন

রোবট ডিজাইন করুন
রোবট ডিজাইন করুন
রোবট ডিজাইন করুন
রোবট ডিজাইন করুন
রোবট ডিজাইন করুন
রোবট ডিজাইন করুন

আমাদের এমন কিছু ডিজাইন করতে হবে যা ইনপুট হপার থেকে একটি একক গুটিকা নিতে পারে, ওয়েবক্যামের নীচে এটি স্থাপন করতে পারে এবং তারপরে এটি উপযুক্ত বিনে স্থানান্তর করতে পারে।

পুঁতি পিকআপ

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

এই ছবিতে, আমি পরীক্ষা করছি যে সিস্টেমটি কাজ করতে পারে। প্লাইউডের উপরের গোলাকার টুকরা ছাড়া সবকিছু ঠিক করা আছে, যা নীচে দেখার বাইরে স্টেপার মোটরের সাথে সংযুক্ত। ওয়েবক্যাম এখনো মাউন্ট করা হয়নি। আমি এই মুহুর্তে মোটর চালু করতে Phidget কন্ট্রোল প্যানেল ব্যবহার করছি।

পুঁতি সংগ্রহস্থল

পরবর্তী অংশ হল প্রতিটি রঙ ধারণের জন্য বিন সিস্টেম ডিজাইন করা। আমি নীচে একটি দ্বিতীয় স্টেপার মোটর ব্যবহার করার সিদ্ধান্ত নিয়েছি এবং সমানভাবে ফাঁকা বগি সহ একটি বৃত্তাকার ধারককে ঘোরানোর জন্য। এটি গর্তের নীচে সঠিক বগিটি ঘোরানোর জন্য ব্যবহার করা যেতে পারে যা থেকে পুঁতি বের হবে।

আমি কার্ডবোর্ড এবং নালী টেপ ব্যবহার করে এটি তৈরি করেছি। এখানে সর্বাধিক গুরুত্বপূর্ণ বিষয় হল ধারাবাহিকতা - প্রতিটি বগি একই আকারের হওয়া উচিত এবং পুরো জিনিসটি সমানভাবে ওজন করা উচিত যাতে এটি এড়িয়ে যাওয়া ছাড়াই ঘুরতে থাকে।

পুঁতি অপসারণ একটি টাইট ফিটিং idাকনার মাধ্যমে সম্পন্ন করা হয় যা একটি সময়ে একটি একক বগি উন্মুক্ত করে, তাই জপমালাগুলি redেলে দেওয়া যায়।

ক্যামেরা

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

Dhaka

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

এটি পরিচালনা করার অনেকগুলি উপায় রয়েছে। আমি একটি 1108 চুম্বকীয় সেন্সর ব্যবহার করার সিদ্ধান্ত নিয়েছি, একটি চুম্বক উপরের প্লেটের প্রান্তে এম্বেড করা আছে। এটি আমাকে প্রতিটি আবর্তনের অবস্থান যাচাই করতে দেয়। একটি ভাল সমাধান সম্ভবত স্টেপার মোটর একটি এনকোডার হতে পারে, কিন্তু আমি একটি 1108 কাছাকাছি মিথ্যা ছিল তাই আমি যে ব্যবহার।

রোবট শেষ করুন

এই মুহুর্তে, সবকিছু কাজ করা হয়েছে, এবং পরীক্ষা করা হয়েছে। সবকিছু সুন্দরভাবে মাউন্ট করার এবং সফ্টওয়্যার লেখার দিকে এগিয়ে যাওয়ার সময় এসেছে।

2 টি স্টেপার মোটর STC1001 স্টেপার কন্ট্রোলার দ্বারা চালিত হচ্ছে। একটি HUB000 - ইউএসবি ভিন্ট হাব স্টেপার কন্ট্রোলার চালানোর জন্য, সেইসাথে চৌম্বক সেন্সর পড়া এবং LED চালানোর জন্য ব্যবহৃত হয়। ওয়েবক্যাম এবং HUB0000 উভয়ই একটি ছোট USB হাবের সাথে সংযুক্ত। একটি 3031 বেণী এবং কিছু তারের একটি 24V পাওয়ার সাপ্লাই সঙ্গে মোটর শক্তি ব্যবহার করা হয়।

ধাপ 3: কোড লিখুন

Image
Image

এই প্রকল্পের জন্য C# এবং ভিজ্যুয়াল স্টুডিও 2015 ব্যবহার করা হয়। এই পৃষ্ঠার শীর্ষে উত্সটি ডাউনলোড করুন এবং অনুসরণ করুন - প্রধান বিভাগগুলি নীচে বর্ণিত হয়েছে

আরম্ভ

প্রথমত, আমাদের অবশ্যই Phidget বস্তু তৈরি, খুলতে এবং শুরু করতে হবে। এটি ফর্ম লোড ইভেন্টে করা হয়, এবং Phidget সংযুক্ত হ্যান্ডলার।

ব্যক্তিগত অকার্যকর Form1_Load (বস্তু প্রেরক, EventArgs e) {

/ * Phidgets আরম্ভ করুন এবং খুলুন */

top. HubPort = 0; top. Attach += Top_Attach; top. Detach += Top_Detach; top. PositionChange += Top_PositionChange; শীর্ষ খোলা ();

নীচে হাবপোর্ট = 1;

নীচে। অ্যাটাচ += নীচে নীচে। নীচে অবস্থান পরিবর্তন += নীচে_ অবস্থান পরিবর্তন; নীচে খোলা ();

magSensor. HubPort = 2;

magSensor. IsHubPortDevice = সত্য; magSensor. Attach += MagSensor_Attach; magSensor. Detach += MagSensor_Detach; magSensor. SensorChange += MagSensor_SensorChange; magSensor. Open ();

নেতৃত্বে হাবপোর্ট = 5;

led. IsHubPortDevice = সত্য; নেতৃত্বাধীন চ্যানেল = 0; নেতৃত্বাধীন। LED. Detach += Led_Detach; নেতৃত্বে খোলা (); }

ব্যক্তিগত অকার্যকর Led_Attach (বস্তু প্রেরক, Phidget22. Events. AttachEventArgs e) {

ledAttachedChk. Checked = সত্য; led. State = সত্য; ledChk. Checked = সত্য; }

ব্যক্তিগত অকার্যকর MagSensor_Attach (বস্তু প্রেরক, Phidget22. Events. AttachEventArgs e) {

magSensorAttachedChk. Checked = সত্য; magSensor. SensorType = VoltageRatioSensorType. PN_1108; magSensor. DataInterval = 16; }

ব্যক্তিগত অকার্যকর Bottom_Attach (বস্তু প্রেরক, Phidget22. Events. AttachEventArgs e) {

bottomAttachedChk. Checked = সত্য; নীচে। CurrentLimit = bottomCurrentLimit; নীচে।নিযুক্ত = সত্য; নীচে। নীচে। নীচে। DataInterval = 100; }

ব্যক্তিগত অকার্যকর Top_Attach (বস্তু প্রেরক, Phidget22. Events. AttachEventArgs e) {

topAttachedChk. Checked = সত্য; top. CurrentLimit = topCurrentLimit; top. Engaged = সত্য; শীর্ষ ।RescaleFactor = -1; top. VelocityLimit = -topVelocityLimit; শীর্ষ ত্বরান্বিতকরণ top. DataInterval = 100; }

আমরা আরম্ভের সময় যে কোনও সংরক্ষিত রঙের তথ্যও পড়ি, তাই পূর্ববর্তী রান চালিয়ে যেতে পারে।

মোটর পজিশনিং

মোটর হ্যান্ডলিং কোড মোটর সরানোর জন্য সুবিধাজনক ফাংশন নিয়ে গঠিত। আমি যে মোটরগুলি ব্যবহার করেছি তা হল বিপ্লব প্রতি 3, 200 1/16 তম ধাপ, তাই আমি এর জন্য একটি ধ্রুবক তৈরি করেছি।

শীর্ষ মোটরের জন্য, 3 টি অবস্থান রয়েছে যা আমরা মোটরকে পাঠাতে সক্ষম হতে চাই: ওয়েবক্যাম, গর্ত এবং পজিশনিং চুম্বক। এই প্রতিটি পদে ভ্রমণের জন্য একটি ফাংশন রয়েছে:

ব্যক্তিগত অকার্যকর nextMagnet (বুলিয়ান অপেক্ষা = মিথ্যা) {

ডবল posn = top. Position % stepsPerRev;

top. TargetPosition += (stepsPerRev - posn);

যদি (অপেক্ষা)

while (top. IsMoving) Thread. Sleep (50); }

ব্যক্তিগত শূন্যতা পরবর্তী ক্যামেরা (বুলিয়ান অপেক্ষা = মিথ্যা) {

ডবল posn = top. Position % stepsPerRev; if (posn <Properties. Settings. Default.cameraOffset) top. TargetPosition += (Properties. Settings. Default.cameraOffset - posn); অন্যথায় শীর্ষ। টার্গেট পজিশন + = ((প্রোপার্টি। সেটিং।

যদি (অপেক্ষা)

while (top. IsMoving) Thread. Sleep (50); }

ব্যক্তিগত শূন্যতা পরবর্তী হোল (বুলিয়ান অপেক্ষা = মিথ্যা) {

ডবল posn = top. Position % stepsPerRev; if (posn <Properties. Settings. Default.holeOffset) top. TargetPosition += (Properties. Settings. Default.holeOffset - posn); অন্যথায় শীর্ষ। টার্গেট পজিশন + = ((প্রোপার্টি।

যদি (অপেক্ষা)

while (top. IsMoving) Thread. Sleep (50); }

একটি রান শুরু করার আগে, উপরের প্লেটটি চৌম্বকীয় সেন্সর ব্যবহার করে সারিবদ্ধ করা হয়। অ্যালাইনমোটর ফাংশনটি উপরের প্লেট সারিবদ্ধ করতে যেকোনো সময় বলা যেতে পারে। এই ফাংশনটি প্রথমে প্লেটটিকে দ্রুত 1 পূর্ণ বিপ্লব পর্যন্ত পরিণত করে যতক্ষণ না এটি একটি চৌম্বক উপাত্তকে থ্রেশহোল্ডের উপরে দেখে। এটি তখন কিছুটা পিছিয়ে যায় এবং ধীরে ধীরে আবার এগিয়ে যায়, সেন্সর ডেটা ক্যাপচার করে। অবশেষে, এটি সর্বোচ্চ চুম্বক ডেটা অবস্থানে অবস্থান সেট করে, এবং অবস্থান অফসেটকে 0 রিসেট করে।

থ্রেড alignMotorThread; বুলিয়ান sawMagnet; ডবল magSensorMax = 0; ব্যক্তিগত অকার্যকর alignMotor () {

// চুম্বক খুঁজুন

top. DataInterval = top. MinDataInterval;

sawMagnet = মিথ্যা;

magSensor. SensorChange += magSensorStopMotor; top. VelocityLimit = -1000;

int tryCount = 0;

আবার চেষ্টা করুন:

top. TargetPosition += stepsPerRev;

while (top. IsMoving &&! sawMagnet) Thread. Sleep (25);

যদি (! sawMagnet) {

যদি (tryCount> 3) {Console. WriteLine ("Align ব্যর্থ"); top. Engaged = মিথ্যা; নীচে।নিযুক্ত = মিথ্যা; runtest = মিথ্যা; প্রত্যাবর্তন; }

tryCount ++;

Console. WriteLine ("আমরা কি আটকে আছি? ব্যাকআপের চেষ্টা করছি …"); top. TargetPosition -= 600; while (top. IsMoving) Thread. Sleep (100);

আবার চেষ্টা করুন;

}

top. VelocityLimit = -100;

magData = নতুন তালিকা> (); magSensor. SensorChange += magSensorCollectPositionData; top. TargetPosition += 300; while (top. IsMoving) Thread. Sleep (100);

magSensor. SensorChange -= magSensorCollectPositionData;

top. VelocityLimit = -topVelocityLimit;

KeyValuePair max = magData [0];

foreach (ম্যাগডাটাতে KeyValuePair পেয়ার) যদি (pair. Value> max. Value) max = pair;

top. AddPositionOffset (-max. Key);

magSensorMax = সর্বোচ্চ মূল্য;

top. TargetPosition = 0;

while (top. IsMoving) Thread. Sleep (100);

Console. WriteLine ("সারিবদ্ধ সফল");

}

তালিকা> magData;

ব্যক্তিগত অকার্যকর magSensorCollectPositionData (বস্তু প্রেরক, Phidget22. Events. VoltageRatioInputSensorChangeEventArgs e) {magData. Add (new KeyValuePair (top. Position, e. SensorValue)); }

ব্যক্তিগত অকার্যকর magSensorStopMotor (বস্তু প্রেরক, Phidget22. Events. VoltageRatioInputSensorChangeEventArgs e) {

যদি (top. IsMoving && e. SensorValue> 5) {top. TargetPosition = top. Position - 300; magSensor. SensorChange -= magSensorStopMotor; sawMagnet = সত্য; }}

সবশেষে, নীচের মোটরটি একটি পুঁতির কন্টেইনার পজিশনে পাঠিয়ে নিয়ন্ত্রণ করা হয়। এই প্রকল্পের জন্য, আমাদের 19 টি পদ রয়েছে। অ্যালগরিদম একটি সংক্ষিপ্ত পথ বেছে নিচ্ছে, এবং ঘড়ির কাঁটার দিকে বা ঘড়ির কাঁটার দিকে ঘুরবে।

ব্যক্তিগত int BottomPosition {get {int posn = (int) bottom. Position % stepsPerRev; যদি (posn <0) posn += stepsPerRev;

return (int) Math. Round (((posn * beadCompartments) / (double) stepsPerRev));

} }

ব্যক্তিগত অকার্যকর SetBottomPosition (int posn, bool wait = false) {

posn = posn % beadCompartments; ডবল targetPosn = (posn * stepsPerRev) / beadCompartments;

ডবল currentPosn = নীচে। অবস্থান % stepsPerRev;

ডবল posnDiff = targetPosn - currentPosn;

// এটি সম্পূর্ণ পদক্ষেপ হিসাবে রাখুন

posnDiff = ((int) (posnDiff / 16)) * 16;

যদি (posnDiff <= 1600) নীচে। TargetPosition += posnDiff; অন্য নীচে। TargetPosition - = (stepsPerRev - posnDiff);

যদি (অপেক্ষা)

যখন (নীচে। }

ক্যামেরা

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

bool runVideo = true; bool videoRunning = false; ভিডিও ক্যাপচার ক্যাপচার; থ্রেড cvThread; রঙ সনাক্ত করা হয়েছে; বুলিয়ান সনাক্তকরণ = মিথ্যা; int detectCnt = 0;

ব্যক্তিগত অকার্যকর cvThreadFunction () {

videoRunning = মিথ্যা;

ক্যাপচার = নতুন ভিডিও ক্যাপচার (নির্বাচিত ক্যামেরা);

ব্যবহার করে (উইন্ডো উইন্ডো = নতুন উইন্ডো ("ক্যাপচার")) {

মাদুর চিত্র = নতুন মাদুর (); মাদুর ইমেজ 2 = নতুন ম্যাট (); while (runVideo) {capt. Read (image); যদি (image. Empty ()) break;

যদি (সনাক্ত করা)

detectCnt ++; অন্যথায় detectCnt = 0;

if (detecting || circleDetectChecked || showDetectionImgChecked) {

Cv2. CvtColor (image, image2, ColorConversionCodes. BGR2GRAY); ম্যাট থ্রেস = ইমেজ ২. থ্রেশহোল্ড ((ডবল) প্রপার্টিস। সেটিংস। thres = thres. GaussianBlur (নতুন OpenCvSharp. Size (9, 9), 10);

যদি (showDetectionImgChecked)

ইমেজ = thres;

যদি (শনাক্ত করা হচ্ছে || circleDetectChecked) {

CircleSegment bead = thres. HoughCircles (HoughMethods. Gradient, 2, /*thres. Rows/4*/ 20, 200, 100, 20, 65); যদি (bead. Length> = 1) {image. Circle (bead [0]. Center, 3, new Scalar (0, 100, 0), -1); image. Circle (পুঁতি [0]। কেন্দ্র, (int) পুঁতি [0]। if (bead [0]. Radius> = 55) {Properties. Settings. Default.x = (decimal) bead [0]. Center. X + (decimal) (bead [0]. Radius / 2); প্রপার্টিসেটিংস.ডেফল্ট.ই = (দশমিক) পুঁতি [0] ।কেন্দ্র। Y - (দশমিক) (পুঁতি [0]। রেডিয়াস / 2); } অন্য {Properties. Settings. Default.x = (দশমিক) পুঁতি [0]. Center. X + (দশমিক) (পুঁতি [0]। রেডিয়াস); বৈশিষ্ট্যাবলী। } Properties. Settings. Default.size = 15; বৈশিষ্ট্যাবলী।সেটিং।ডিফল্ট।হাইট = 15; } অন্য {

CircleSegment বৃত্ত = thres. HoughCircles (HoughMethods. Gradient, 2, /*thres. Rows/4*/ 5, 200, 100, 60, 180);

if (circle. Length> 1) {List xs = circle. Select (c => c. Center. X). ToList (); xs. Sort (); তালিকা ys = চেনাশোনা। (c => c. Center. Y) নির্বাচন করুন। ys. Sort ();

int medianX = (int) xs [xs. Count / 2];

int medianY = (int) ys [ys. Count / 2];

if (medianX> image. Width - 15)

medianX = image. প্রস্থ - 15; if (medianY> image. Height - 15) medianY = image. Height - 15;

image. Circle (medianX, medianY, 100, new scalar (0, 0, 150), 3);

যদি (সনাক্ত করা) {

বৈশিষ্ট্যাবলী। বৈশিষ্ট্যাবলী। Setting. Default.y = medianY - 7; প্রোপার্টি।সেটিংস। ডিফল্ট.সাইজ = 15; বৈশিষ্ট্যাবলী।সেটিং।ডিফল্ট।হাইট = 15; }}}}}

Rect r = new Rect ((int) Properties. Settings. Default.x, (int) Properties. Settings. Default.y, (int) Properties. Settings. Default.size, (int) Properties. Settings. Default.height);

মাদুর beadSample = নতুন মাদুর (ছবি, r);

Scalar avgColor = Cv2. Mean (beadSample); detectColor = Color. FromArgb ((int) avgColor [2], (int) avgColor [1], (int) avgColor [0]);

চিত্র আয়তক্ষেত্র (r, নতুন স্কেলার (0, 150, 0));

window. ShowImage (ছবি);

Cv2. WaitKey (1); videoRunning = সত্য; }

videoRunning = মিথ্যা;

} }

ব্যক্তিগত অকার্যকর ক্যামেরা স্টার্টবিটিএন_ক্লিক (বস্তু প্রেরক, ইভেন্টআর্গস ই) {

যদি (cameraStartBtn. Text == "start") {

cvThread = নতুন থ্রেড (নতুন থ্রেড স্টার্ট (cvThreadFunction)); রানভিডিও = সত্য; cvThread. Start (); cameraStartBtn. Text = "স্টপ"; যখন (! videoRunning) থ্রেড। ঘুম (100);

updateColorTimer. Start ();

} অন্য {

রানভিডিও = মিথ্যা; cvThread. Join (); cameraStartBtn. Text = "শুরু"; }}

রঙ

এখন, আমরা একটি পুঁতির রঙ নির্ধারণ করতে সক্ষম, এবং সেই রঙের উপর ভিত্তি করে সিদ্ধান্ত নিই কোন পাত্রে এটি ফেলে দেওয়া হবে।

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

রঙের পার্থক্য গণনার জন্য জটিল অ্যালগরিদম রয়েছে। আমরা CIE2000 ব্যবহার করি, যা 1 এর কাছাকাছি একটি সংখ্যা আউটপুট করে যদি 2 টি রং মানুষের কাছে আলাদা না হয়। আমরা এই জটিল হিসাব করতে ColorMine C# লাইব্রেরি ব্যবহার করছি। মিথ্যা ইতিবাচক এবং মিথ্যা নেতিবাচক মধ্যে একটি ভাল সমঝোতা প্রস্তাব 5 একটি DeltaE মান পাওয়া গেছে।

যেহেতু পাত্রে প্রায়শই অনেক বেশি রঙ থাকে, শেষ অবস্থানটি ক্যাচাল বিন হিসাবে সংরক্ষিত থাকে। আমি সাধারণত মেশিনটি দ্বিতীয় পাসে চালানোর জন্য এইগুলিকে আলাদা করে রাখি।

তালিকা

রং = নতুন তালিকা (); তালিকা রঙ প্যানেল = নতুন তালিকা (); তালিকা রং Txts = নতুন তালিকা (); তালিকা colorCnts = নতুন তালিকা ();

const int numColorSpots = 18;

const int unknownColorIndex = 18; int findColorPosition (রঙ c) {

কনসোল।রাইটলাইন ("রঙ খোঁজা …");

var cRGB = নতুন Rgb ();

cRGB. R = c. R; cRGB. G = c. G; cRGB. B = c. B;

int bestMatch = -1;

ডবল ম্যাচ ডেল্টা = 100;

জন্য (int i = 0; i <colors. Count; i ++) {

var RGB = নতুন Rgb ();

RGB. R = রং . R; RGB. G = রং . G; RGB. B = রং . B;

ডাবল ডেল্টা = cRGB। তুলনা করুন (RGB, নতুন CieDe2000Comparison ());

// ডাবল ডেল্টা = ডেল্টা ই (সি, কালার [আই]); Console. WriteLine ("DeltaE (" + i. ToString () + "):" + delta. ToString ()); যদি (delta <matchDelta) {matchDelta = delta; bestMatch = i; }}

যদি (matchDelta <5) {Console. WriteLine ("পাওয়া গেছে! (Posn:" + bestMatch + "Delta:" + matchDelta + ")"); সেরা ম্যাচ ফিরুন; }

if (colors. Count <numColorSpots) {Console. WriteLine ("New Color!"); রং যোগ করুন (গ); এই। writeOutColors (); ফেরত (রং। গণনা - 1); } অন্যথায় {Console. WriteLine ("Unknown Color!"); ফেরত অজানা কালার ইন্ডেক্স; }}

সাজানোর যুক্তি

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

থ্রেড colourTestThread; বুলিয়ান রানটেস্ট = মিথ্যা; অকার্যকর রঙ পরীক্ষা () {

if (! top। Engaged)

top. Engaged = সত্য;

যদি (! নীচে। সংযুক্ত)

নীচে।নিযুক্ত = সত্য;

while (runtest) {

nextMagnet (সত্য);

থ্রেড ঘুম (100); চেষ্টা করুন {if (magSensor. SensorValue <(magSensorMax - 4)) alignMotor (); } ধরা {alignMotor (); }

পরবর্তী ক্যামেরা (সত্য);

সনাক্তকরণ = সত্য;

যখন (detectCnt <5) Thread. Sleep (25); কনসোল। সনাক্তকরণ = মিথ্যা;

রঙ c = সনাক্তকৃত রঙ;

এই। int i = findColorPosition (c);

SetBottomPosition (i, true);

নেক্সটহোল (সত্য); colorCnts ++; এই। থ্রেড ঘুম (250);

যদি (colorCnts [unknownColorIndex]> 500) {

top. Engaged = মিথ্যা; নীচে।নিযুক্ত = মিথ্যা; runtest = মিথ্যা; এই। প্রত্যাবর্তন; }}}

ব্যক্তিগত অকার্যকর colourTestBtn_Click (বস্তু প্রেরক, EventArgs ই) {

যদি (colourTestThread == null ||! colourTestThread. IsAlive) {colourTestThread = নতুন থ্রেড (নতুন থ্রেডস্টার্ট (colourTest)); runtest = সত্য; colourTestThread. Start (); colourTestBtn. Text = "STOP"; colourTestBtn. BackColor = Color. Red; } অন্য {runtest = মিথ্যা; colourTestBtn. Text = "GO"; colourTestBtn. BackColor = রঙ সবুজ; }}

এই মুহুর্তে, আমাদের একটি কর্মসূচি রয়েছে। কোডের কিছু বিট নিবন্ধের বাইরে রেখে দেওয়া হয়েছিল, তাই এটি চালানোর জন্য উৎসটি দেখুন।

অপটিক্স প্রতিযোগিতা
অপটিক্স প্রতিযোগিতা

অপটিক্স প্রতিযোগিতায় দ্বিতীয় পুরস্কার

প্রস্তাবিত: