PDA

View Full Version : پردازش تصویر



ali_72
چهارشنبه 02 اردیبهشت 1394, 12:30 عصر
سلام

یه تصویر رنگی دارم
با کدنویسی سیاه و سفیدش کردم
تصویر تبدیل به bitmap کردم
با 2 تا for من میتونم رنگ تک تک پیکسل های تصویرم رو داشته باشم
حالا من می خوام یه مستطیل تو این تصویر رو مشخص کنم
زمینه تصویر روشنه ولی یه سری چیزهای کوچک تیره هم در اون دیده می شه
میدونم که باید ناحیه ای از تصویر select شه که بیشترین چگالی رنگ تیره رو داشته باشه
لطفا راهنمایی کنید
ممنونم

Alireza_1387
چهارشنبه 02 اردیبهشت 1394, 15:03 عصر
سلام

یه تصویر رنگی دارم
با کدنویسی سیاه و سفیدش کردم
تصویر تبدیل به bitmap کردم
با 2 تا for من میتونم رنگ تک تک پیکسل های تصویرم رو داشته باشم
حالا من می خوام یه مستطیل تو این تصویر رو مشخص کنم
زمینه تصویر روشنه ولی یه سری چیزهای کوچک تیره هم در اون دیده می شه
میدونم که باید ناحیه ای از تصویر select شه که بیشترین چگالی رنگ تیره رو داشته باشه
لطفا راهنمایی کنید
ممنونم
به شما پیشنهاد می کنم از کتابخانه OpenCV استفاده کنین . همین طوری بدون استفاده از کتابخانه کارتون خیلی سخت میشه

چندتا سایت خوب برای شروع :
http://iroref.ir/%DA%A9%D8%AA%D8%A7%D8%A8-%D8%AE%D9%88%D8%AF%D8%A2%D9%85%D9%88%D8%B2-%D8%A7%D9%BE%D9%86-%D8%B3%DB%8C-%D9%88%DB%8C-%D8%A2%D9%85%D9%88%D8%B2%D8%B4-opencv/

http://opencv.ir/forum

http://robotical.ir/%D8%A2%D9%85%D9%88%D8%B2%D8%B4-%D8%AA%D8%B5%D9%88%DB%8C%D8%B1%DB%8C-%D9%BE%D8%B1%D8%AF%D8%A7%D8%B2%D8%B4-%D8%AA%D8%B5%D9%88%DB%8C%D8%B1-%D8%A8%D8%A7-opencv-%D9%82%D8%B3%D9%85%D8%AA-%D8%A7%D9%88%D9%84/

ali_72
شنبه 05 اردیبهشت 1394, 14:52 عصر
با کتابخونه opencv نتونستم به نتیجه دلخواهم برسم
همیشه باید پارامترها رو تغییر بدم

و اینکه میخوام مساحت مستطیل رو حساب کنم

fafa_n6190
شنبه 05 اردیبهشت 1394, 15:13 عصر
با توجه به جدا بودن تالار پردازش تصویر امیدوارم تاپیکتون به وسیله مدیرا پاک نشه!
اگه میخواهید توی C# این کار رو انجام بدید پیشنهاد میکنم از emgu (http://www.emgu.com) استفاده بکنید که wrapper opencv برای دات نت هست!
اگه منظورتون رو متوجه شده باشم باید contour هایی روی تصویرتون پیدا کنید (با تابع FindCounturs) و بزرگترینش رو پیدا کنید و با استفاده از تابع GetMinAreaRect مستطیل مورد نظر رو بدست بیارید.

ali_72
یک شنبه 06 اردیبهشت 1394, 09:00 صبح
ممنون دوست عزیز
از مواردی که گفتی استفاده کردم
ولی باز هم نتیجه اون چیزی نشد که می خواستم (تنها بخشی از مستطیل انتخاب شد و لبه های مستطیل کاملا به هم متصل نشدند و مستطیل کامل تشکیل نشده)
در ضمن تابع
GetMinAreaRect برای پیدا کردن مستطیل با کمترین مساحت استفاده می شه من به مستطیل با کمترین مساحت نیازی ندارم
خروجی کد من این شد:

130630


private void button2_Click(object sender, EventArgs e) {

Bitmap bmp = new Bitmap(@"G:\1.png");
//خواندن تصاویر از داخل فایل‌هایی که بر روی دیسک قرار دارند
Image<Bgr, Byte> img = new Image<Bgr, byte>(bmp);
//تبدیل یک تصویر رنگی به تصویر خاکستری
Image<Gray, Byte> gray = img.Convert<Gray, Byte>().PyrDown().PyrUp();
Gray cannyThreshold = new Gray(Convert.ToInt32(textBox2.Text));//80
Gray cannyThresholdLinking = new Gray(Convert.ToInt32(textBox1.Text));//120
Gray circleAccumulatorThreshold = new Gray(120);

Image<Gray, Byte> cannyEdges = gray.Canny(cannyThreshold, cannyThresholdLinking).Not();


Bitmap color;
Bitmap bgray;
IdentifyContours(cannyEdges.Bitmap, 50, true, out bgray, out color);


circleImageBox.Image = color;
}
public void IdentifyContours(Bitmap colorImage, int thresholdValue, bool invert, out Bitmap processedGray, out Bitmap processedColor)
{
Image<Gray, byte> grayImage = new Image<Gray, byte>(colorImage);
Image<Bgr, byte> color = new Image<Bgr, byte>(colorImage);


grayImage = grayImage.ThresholdBinary(new Gray(thresholdValue), new Gray(255));


if (invert)
{
//معکوس کردن یک تصویر خاکستری یا باینری
grayImage._Not();
}
Contour<Point> largestContour = null;
double largestarea = 0;
using (MemStorage storage = new MemStorage())
{


for (Contour<Point> contours = grayImage.FindContours(Emgu.CV.CvEnum.CHAIN_APPROX _METHOD.CV_CHAIN_APPROX_SIMPLE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_LIST, storage); contours != null; contours = contours.HNext)
{


if (contours.Area > largestarea)
{
largestarea = contours.Area;
largestContour = contours;
}


}
if (largestContour != null)

CvInvoke.cvDrawContours(color, largestContour, new MCvScalar(255), new MCvScalar(255), -1, 1, Emgu.CV.CvEnum.LINE_TYPE.EIGHT_CONNECTED, new Point(0, 0));
color.Draw(largestContour.BoundingRectangle, new Bgr(0, 255, 0), 1);
}
}


processedColor = color.ToBitmap();
processedGray = grayImage.ToBitmap();


}




من برای cannyThreshold (آستانه تشخیص لبه) و cannyThresholdLinking (آستانه لینک کردن لبه ها) دقیقا نمیدونم چه اعدادی باید بذارم
ولی مرتب این 2 را تغییر دادم تا مثلا 80 و 120 این تصویر را بدست آوردم

fafa_n6190
یک شنبه 06 اردیبهشت 1394, 12:54 عصر
میشه روی تصویر ورودی سوالتون رو مطرح کنید؟
سوال هنوز گنگه برای من! اگه قصد تشخیص مستطیل رو دارید توی مثال های خود emgu نمونه مثال (http://www.emgu.com/wiki/index.php/Shape_%28Triangle,_Rectangle,_Circle,_Line%29_Dete ction_in_CSharp)مناسبی وجود داره!

130638

ali_72
دوشنبه 07 اردیبهشت 1394, 07:25 صبح
میخوام توی عکس مستطیل رو انتخاب کنم و مساحتشو رو محاسبه کنم


دقیقا از مثالی که گفتی استفاده کردم
ولی این مثال برای تصاویری مثل اون که خودش گذاشته درست عمل میکنه (بکگراند تک رنگ و اشکال کاملا مشخص)
من از این کد استفاده کردم ولی برای تصویر من هیچ چیزی انتخاب نشد
ممنون میشم به کد من یه نگاهی بندازی و بگی کجا اشتبا می کنم




private void button8_Click(object sender, EventArgs e)
{
Bitmap bmp = new Bitmap(@"G:\1.png");
//خواندن تصاویر از داخل فایل‌هایی که بر روی دیسک قرار دارند
Image<Bgr, Byte> img = new Image<Bgr, byte>(bmp);
//تبدیل یک تصویر رنگی به تصویر خاکستری
Image<Gray, Byte> gray = img.Convert<Gray, Byte>().PyrDown().PyrUp();
//آستانه تشخیص لبه
Gray cannyThreshold = new Gray(Convert.ToInt32(textBox2.Text));//80
//آستانه لینک کردن لبه ها
Gray cannyThresholdLinking = new Gray(Convert.ToInt32(textBox1.Text));//120

Image<Gray, Byte> cannyEdges = gray.Canny(cannyThreshold, cannyThresholdLinking).Not();


Bitmap color;
Bitmap bgray;
IdentifyContours2(cannyEdges.Bitmap, 50, true, out bgray, out color);


circleImageBox.Image = color;
}
public void IdentifyContours2(Bitmap colorImage, int thresholdValue, bool invert, out Bitmap processedGray, out Bitmap processedColor)
{
List<MCvBox2D> boxList = new List<MCvBox2D>(); //a box is a rotated rectangle
Image<Gray, byte> grayImage = new Image<Gray, byte>(colorImage);
Image<Bgr, byte> color = new Image<Bgr, byte>(colorImage);


grayImage = grayImage.ThresholdBinary(new Gray(thresholdValue), new Gray(255));


if (invert)
{
//معکوس کردن یک تصویر خاکستری یا باینری
grayImage._Not();
}
Contour<Point> largestContour = null;
double largestarea = 0;
using (MemStorage storage = new MemStorage())
{


for (Contour<Point> contours = grayImage.FindContours(Emgu.CV.CvEnum.CHAIN_APPROX _METHOD.CV_CHAIN_APPROX_SIMPLE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_LIST, storage); contours != null; contours = contours.HNext)
{


Contour<Point> currentContour = contours.ApproxPoly(contours.Perimeter * 0.015, storage);


//if (contours.Area > 250)
//{
if (currentContour.Total == 4) //The contour has 4 vertices.
{
#region determine if all the angles in the contour are within [80, 100] degree
bool isRectangle = true;
Point[] pts = currentContour.ToArray();
LineSegment2D[] edges = PointCollection.PolyLine(pts, true);


for (int i = 0; i < edges.Length; i++)
{
double angle = Math.Abs(
edges[(i + 1) % edges.Length].GetExteriorAngleDegree(edges[i]));
if (angle < 80 || angle > 100)
{
isRectangle = false;
break;
}
}
#endregion


if (isRectangle) boxList.Add(currentContour.GetMinAreaRect());
}
//}


}

}


processedColor = color.ToBitmap();
processedGray = grayImage.ToBitmap();


}

fafa_n6190
دوشنبه 07 اردیبهشت 1394, 09:21 صبح
دریافت پروژه (http://s6.picofile.com/file/8185091484/box.rar.html)

ali_72
سه شنبه 08 اردیبهشت 1394, 07:40 صبح
ممنون دوست عزیز
متوجه یک اشکال بزرگ در کدنویسی هام شدم
من هم از روش ماسک کردن تصویر استفاده کرده بودم ولی با مقادیری دیگر از hsv lower و hsv higher
و از عملیات مورفولوژی روی تصویر هم استفاده نمی کردم
این باعث می شد به نتیجه نرسم
ولی این باز هم مشکل من میشه
چطور برای یه تصویر Hue min و Hue max و Sat min و Sat max و value min , max و Erode و Dilate را انتخاب می کنید
همه اینا روی درست ماسک شدن تصویر و در نتیجه پردازش تصویر اهمیت داره
درباره مدل رنگ hsv و مقادیر مجاز h و s و v مطالعه کردم
ولی درباره هر تصویر حتی هم گروه (شبیه هم) باید این مقادیر و Erode و Dilate را تغییر بدم تا به نتیجه مورد نظر برسم
معیار انتخاب چی باشه تا سریع به نتیجه برسم
ممنون میشم راهنمایی کنید

ali_72
چهارشنبه 09 اردیبهشت 1394, 07:17 صبح
چطور میشه از یک تصویر hsv اونو بدست آورد؟

fafa_n6190
دوشنبه 14 اردیبهشت 1394, 01:27 صبح
با تابع InRange شما می تونید با دادن HsvMin و HsvMax فیتر رنگ رو روی تصویرتون اعمال کنید و تصویر رو ماسک کنید تا اطلاعات اضافی از تصویر حذف بشن ، درواقع فقط رنگ های مجاز که در بازه داده شده قرار دارند باقی میمونن ، پیدا کردن این بازه به راحتی و با کوچک کردن بازه از دو طرف تا مرز رنگ مورد نظر انجام میگیره! به اصطلاح بهش میگن Grab کردن رنگ

وقتی تصویر ورودی رو قرار میدید ابتدا بازه H رو از پایین و بالا تا حد امکان کوچک کنید تا فقط رنگ مورد نظر شما بمونه سپس به ترتیب برای S و V این کار رو از پایین انجام بدین!
در نهایت تصویر باینری تولید میشه که ماسک تصویر شما توی اون بازه رنگیه! حالا تابع Erode جهت از بین بردن نویز ها به کار گرفته میشه ، این تابع کمی از حجم جزایر رنگ سفید (couture) هاتون رو میگیره (تا جایی که باعث میشه حتی بخشی از اونها که خیلی کوچک هستند کلا از بین میرن) و سپس تابع Dilate به couture های باقی مانده مقداری حجم میده.
تمام این پارامتر ها به صورت تجربی و با آزمون و خطا و نمونه برداری از رنگ خود شی تعیین میشه ،

یه تیکه فیلم (http://s4.picofile.com/file/8186554442/Color_detection_in_Hsv_with_Emgu.mp4.html) کوچیک از این کار برات میگذارم


130841

ali_72
دوشنبه 14 اردیبهشت 1394, 07:46 صبح
با تابع InRange شما می تونید با دادن HsvMin و HsvMax فیتر رنگ رو روی تصویرتون اعمال کنید و تصویر رو ماسک کنید تا اطلاعات اضافی از تصویر حذف بشن ، درواقع فقط رنگ های مجاز که در بازه داده شده قرار دارند باقی میمونن ، پیدا کردن این بازه به راحتی و با کوچک کردن بازه از دو طرف تا مرز رنگ مورد نظر انجام میگیره! به اصطلاح بهش میگن Grab کردن رنگ

وقتی تصویر ورودی رو قرار میدید ابتدا بازه H رو از پایین و بالا تا حد امکان کوچک کنید تا فقط رنگ مورد نظر شما بمونه سپس به ترتیب برای S و V این کار رو از پایین انجام بدین!
در نهایت تصویر باینری تولید میشه که ماسک تصویر شما توی اون بازه رنگیه! حالا تابع Erode جهت از بین بردن نویز ها به کار گرفته میشه ، این تابع کمی از حجم جزایر رنگ سفید (couture) هاتون رو میگیره (تا جایی که باعث میشه حتی بخشی از اونها که خیلی کوچک هستند کلا از بین میرن) و سپس تابع Dilate به couture های باقی مانده مقداری حجم میده.
تمام این پارامتر ها به صورت تجربی و با آزمون و خطا و نمونه برداری از رنگ خود شی تعیین میشه ،

یه تیکه فیلم (http://s4.picofile.com/file/8186554442/Color_detection_in_Hsv_with_Emgu.mp4.html) کوچیک از این کار برات میگذارم


130841

مرسی دنبال راهی هستم که با آنالیز تصویر حداقل نیاز به کاربر برای بدست آوردن پارامترهای رنگ تصویر را بدست بیارم