PDA

View Full Version : سوال: علامتگذاری بر روی عکس



adineh67
پنج شنبه 20 آذر 1393, 09:29 صبح
سلام به دوستان برنامه نویس
یه تصویر دارم که طبق محاسباتی تو برنامم باید یه سری از پیکسلای این تصویر رو به عنوان نتیجه محاسباتم مجزا کنم این کارو با تغییر رنگ پیکسل مورد نظر انجام میدم
مشکلی که پیش میاد اینه که پیکسل خیلی ریز هست و کاربر به سختی متوجه این تغییر رنگ میشه.
مد نظرم اینه که یه علامت داشته باشم که به اون پیکسلی که تغییر رنگ داده اشاره کنه،به ازای هر پیکسل یه علامت.چیزی شبیه به بالن های کوچیک روی نقشه ها که واسه مشخص کردن مکانها بکار میرن
ممنون میشم هر راهنمایی که به ذهنتون میرسه بهم بگید
کارم خیلی گیر :گریه:

plus
پنج شنبه 20 آذر 1393, 20:28 عصر
میتونید اول یک تصویر بالن که مورد نظرتون هست تهیه کنید و بعد با متد DrawImage کلاس Graphics روی Bitmap مورد نظر با توجه به محل پیکسل رسمش کنید.

adineh67
پنج شنبه 27 آذر 1393, 21:49 عصر
دوستان امکانی هست که بشه همون تصویر رسم شده روی تصویر اصلی رو با کلیک کردن تشخیص داد؟!

plus
پنج شنبه 27 آذر 1393, 22:11 عصر
مختصات و اندازه تصویر رسم شده رو جایی نگه دارین و موقعی که کاربر روی تصویراصلی (احتمالا توی یک PictureBox) کلیک میکنه، بر اساس مختصات نشانگر موس، بررسی کنید که آیا در محدوده مربوطه کلیک شده یا نه.
رویدادهای مربوط به موس آرگومانی از نوع MouseEventArgs دارن که مختصات موس رو نسبت به بالا سمت چپ کنترل به شما میده.اگه محل تصویر رو در یک شی Rectangle نگه داشته باشین، میتونید با استفاه از متد Contains بررسی رو انجام بدین.

adineh67
پنج شنبه 27 آذر 1393, 22:33 عصر
خیلی ممنونم از لطفتون
فقط من از اون شی رسم شده شاید بیش از هزارتا داشته باشم مختصاتشون رو کجا ذخیره کنم بهتره؟

plus
پنج شنبه 27 آذر 1393, 23:05 عصر
اصل مختصات بهتره در یک شی یا آرایه ای از Rectangle نگه داری بشه.اگه اینکه دقیقا شما چطوری نگه داری کنید بستگی به مساله شما داره.مثلا شما ممکنه بخواین اطلاعاتی در مورد اینکه کدوم شکل کلیک شده هم داشته باشین.در صورت صورت باید شی Rectangle رو همراه یک فیلد مشخص کننده مثلا Id یا یک فیلد tag که مشخص میکنه مربوط به مختصات کدوم تصویر یا شی هست رو در یک کلاس یا struct دیگه تعریف کنید و آرایه ای از اون رو داشته باشید.با داشتن این آرایه میتونین با کلیک کاربر روی تصویر اصلی، این آرایه رو پیمایش کنید و تصویر و یا تصاویری در روشون کلیک شده رو دربیارین.

struct FlagInfo {
private Rectangle bounds;
private int id;
public FlagInfo(int id, Rectangle bounds) {
this.id = id;
this.bounds = bounds;
}
public Rectangle Bounds {
get {
return this.bounds;
}
}
public int Id {
get {
return this.id;
}
}
}

plus
پنج شنبه 27 آذر 1393, 23:07 عصر
(ای بابا باز پست تکراری...امان ازین چیز شکن ها!)

adineh67
جمعه 28 آذر 1393, 10:00 صبح
سلام دوست عزیز کدی که نوشتین واسه عکسهایی که رو هم قرار میگیرن جواب میده؟
کار من به این شکل هست که یه سری پیکسل رو توسط بالن های کوچیک بر روی تصویر اصلی مجزا میکنم و با کلیک روی هر بالن باید اطلاعات اون پیکسل نمایش داده بشه حالا ممکنه دو تا تصویر با فاصله ی کمی از هم قرار داشته باشن موقع کلیک کردن چطور میتونم از هم مجزاشون کنم در صورتی که تو ناحیه ی همدیگه قرار دارن؟!!!! :متفکر:

plus
جمعه 28 آذر 1393, 11:39 صبح
با روشی که برای نگه داری گفتم شما میتونی تشخیص بدی که یک یا چند بالن کلیک شده.اما برای حالتی که چند بالن کلیک میشه باید یک راه حل پیدا کنید.
یک راه ساده اما نه چندان کاربر پسند این هست که در این حالت، بررسی کنید ببینید نقطه ای که کلیک شده به مرکز (یا مثلا بالای) کدوم بالن نزدیکتر هست و اون رو انتخاب کنید.
راه دیگه که سخت تر هست اما کاربر پسند تر استفاده از روشی مثل کروم در اندروید هست.زمانی که روی دو لینک مجاور تاچ بشه، تصویر بزرگتر شده ای از اون ناحیه به کاربر نمایش داده میشه و کاربر میتونه اینبار روی یکیشون تاچ انجام بده.

adineh67
جمعه 28 آذر 1393, 14:34 عصر
دقیقتر برناممو توضیح میدم تا کدی که نوشتم واستون روشن شه
سه تا مختصات دارم که طبق تصویر محور بالایی برای نمایش x و y و محور پایینی برای نمایش x و z استفاده می شه. اطلاعات توی یه گریدویو قرار دارن که سطرها یکی یکی پیمایش می شن و مختصاتشون روی محور پیدا شده و جاش یه بالن درج می شه.



126707

حالا می خوام رو هر بالن که کلیک کردم اطلاعات مربوط به اون مختصات رو بهم بده مختصات صحیح مختصاتی هست که بالن داره بهش اشاره میکنه اما چون خیلی ریز هست و کاربر به راحتی نمیتونه روش کلیک کنه کل اون بالن رو در نظر گرفتم و گفتم اگه ناحیه ی کلیک شده در محدوده ای باشه که بالن قرار داره اطلاعات مربوط به اون رو نشون بده.حالا مشکلی که واسم پیش اومده اینه که ممکنه تو محدوده ی یک بالن،بالن دیگه ای هم قرار داشته باشه که باعث میشه اطلاعات اون ناحیه هم نمایش داده بشه واسه این مورد راهی به ذهنم نمیرسه ممنون میشم با توجه به کدی که نوشتم راهنماییم کنید



private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
{
dt.Clear();
object[] list = new object[dt.Columns.Count];
int x = e.Location.X;
if (x < 501)
x = x * (-1);
int y = e.Location.Y;
if (y > 126)
y = y * (-1);
int minx, muxx, miny, muxy;
for (int i = 0; i < dataGridView1.RowCount; i++)
{
int xx = Convert.ToInt32(dataGridView1.Rows[i].Cells[13].Value);
xx = xx / 2;
if (xx < 0)
xx = (501 - xx) * (-1);
else
xx = xx + 501;
int yy = Convert.ToInt32(dataGridView1.Rows[i].Cells[14].Value);
yy = yy / 4;
if (yy <= 0)
{
yy = yy * (-1);
yy = (126 + yy);
}
else
{
yy = yy - 126;
if (yy < 0)
yy = yy * (-1);
}
minx = xx - 8;
if (minx < 0) minx = minx * (-1);
muxx = xx + 8;
miny = yy - 16;
if (miny < 0) miny = miny * (-1);
muxy = yy + 16;
if ((x>=minx && x<=muxx )&&(y>=miny && y<=muxy))
{

list[0] = dataGridView1.Rows[i].Cells[0].Value;
list[1] = dataGridView1.Rows[i].Cells[1].Value;
list[2] = dataGridView1.Rows[i].Cells[2].Value;
list[3] = dataGridView1.Rows[i].Cells[3].Value;
list[4] = dataGridView1.Rows[i].Cells[4].Value;
list[5] = dataGridView1.Rows[i].Cells[5].Value;
list[6] = dataGridView1.Rows[i].Cells[6].Value;
list[7] = dataGridView1.Rows[i].Cells[7].Value;
list[8] = dataGridView1.Rows[i].Cells[8].Value;
list[9] = dataGridView1.Rows[i].Cells[9].Value;
list[10] = dataGridView1.Rows[i].Cells[10].Value;
list[11] = dataGridView1.Rows[i].Cells[11].Value;
list[12] = dataGridView1.Rows[i].Cells[12].Value;
list[13] = dataGridView1.Rows[i].Cells[13].Value;
list[14] = dataGridView1.Rows[i].Cells[14].Value;
list[15] = dataGridView1.Rows[i].Cells[15].Value;
list[16] = dataGridView1.Rows[i].Cells[16].Value;
list[17] = dataGridView1.Rows[i].Cells[17].Value;
list[18] = dataGridView1.Rows[i].Cells[18].Value;
list[19] = dataGridView1.Rows[i].Cells[19].Value;
list[20] = dataGridView1.Rows[i].Cells[20].Value;
list[21] = dataGridView1.Rows[i].Cells[21].Value;
list[22] = dataGridView1.Rows[i].Cells[22].Value;
list[23] = dataGridView1.Rows[i].Cells[23].Value;
dt.Rows.Add(list);
}

}
if (dt.Rows.Count != 0)
{
InfoSegment newfrm = new InfoSegment(dt);
newfrm.Show(this);
}
}

adineh67
جمعه 28 آذر 1393, 14:48 عصر
توضیحات کد: (501،126) نقطه ی (0،0) محور مختصاتم هستن و چون بالن به نسبت گوشه ی بالا سمت چپ ست میشه از x هشت تا و از Y شانزده واحد کم کردم تا تصویر بالن دقیقا به مختصات مورد نظرم اشاره کنه
چون اندازه ی فرمم محدود هست از اندازه های اصلی مقیاس گرفتم و x های اصلی رو به 2 و y های اصلی رو به 4 تقسیم کردم.اندازه ی محور x = 0..1002 و اندازه محور Y یا Z برابر 252..0 هست.
تصویر بالن 32*32 هست و وقتی میخوام کل ناحیه مربوط به اون رو در نظر بگیرم از این کد استفاده کردم


minx = xx - 8; if (minx < 0) minx = minx * (-1);
muxx = xx + 8;
miny = yy - 16;
if (miny < 0) miny = miny * (-1);
muxy = yy + 16;

plus
جمعه 28 آذر 1393, 18:43 عصر
البته از Rectangle استفاده نکردین و من نقش DataGridView رو متوجه نشدم ولی دو قسمت به کدتون اضافه کردم که در با بررسی فاصله نقطه کلیک شده با مرکز بالن، فقط اون آیتمی در dt نگه میداره که نقطه به مرکز بالنش نزدیک تره:

int closestSegmentIndex = -1;
double closestDistance = double.MaxValue;
for (int i = 0; i < dataGridView1.RowCount; i++)
{
..
..
..
..
if ((x>=minx && x<=muxx )&&(y>=miny && y<=muxy))
{
PointF center = new PointF((muxx - minx) / 2.0f, (muxy - miny) / 2.0f);
double distance = Math.Sqrt((x - center.X) ^ 2 + (y - center.Y) ^ 2);
if (distance < closestDistance)
{
closestSegmentIndex = i;
closestDistance = distance;
list[0] = dataGridView1.Rows[i].Cells[0].Value;
list[1] = dataGridView1.Rows[i].Cells[1].Value;
...
...
list[23] = dataGridView1.Rows[i].Cells[23].Value;
dt.Clear();
dt.Rows.Add(list);
}
}
}
if (dt.Rows.Count != 0)
{
InfoSegment newfrm = new InfoSegment(dt);
newfrm.Show(this);

}

در کل چند خط کل قبل از for اضافه شده و بعد از شرط if شما هم مقدار کد اضافه شده. اونجاهایی که ... گذاشتم رو از کد خودتون جایگزین کنید.
البته لزومی در استفاده از dt نبوده و کد بهینه نیست فقط برای اینکه منظورم رو متوجه بشین و کمترین تغییر توی کدتون ایجاد بشه.
بالای for دو متغیر ایجاد شدن که به ترتیب اندیس نزدیک ترین بالن و فاصله نقطه با مرکز اون بالن نگه داری میشه.
اینجا:

PointF center = new Point((muxx - minx) / 2.0f, (muxy - miny) / 2.0f);
double distance = Math.Sqrt((x - center.X) ^ 2 + (y - center.Y) ^ 2);
if (distance < closestDistance)
{
closestSegmentIndex = i;
closestDistance = distance;[

اینطور که من فهمیدم minx و muxx به همراه miny و muxy محدوده بالن رو (به صورت نسبی) مشخص میکنن.در صورتی که نقطه کلیک شده در محدوده باشه ما با فرمول محاسبه فاصله، فاصله نقطه رو از مرکزش بدست میاریم و در صورتی که از آخرین فاصله بدست اومده کمتر بود dt رو پاک میکنیم و اون رو به dt، به جای قبلی اضافه میکنیم.

adineh67
جمعه 28 آذر 1393, 18:58 عصر
دیتا گریدویو مشخصات قطعاتی رو نگه میداره که مختصاتشون توسط بالن بر روی محور تعیین شده.کدم قطعا بهینه نیست چون فقط خواستم جواب بگیرم وقتی واسه بهینه سازی نذاشتم
بینهایت سپاسگذارم :لبخندساده:

adineh67
جمعه 28 آذر 1393, 19:27 عصر
دوست عزیز کدی که نوشتین مشکل قبلیو حل کرد فقط موردی که الان پیش اومده اینه که بعضی قطعات مختصات مشابهی دارن که این کد فقط یک مورد از اونا رو نشون میده در صورتی که باید وقتی رو مختصات موردنظر کلیک کردم باید همه ی قطعات دارای اون مختصات رو برگردونه.واسه این منظور بود که از dt استفاده کردم

plus
جمعه 28 آذر 1393, 19:46 عصر
شرط به این صورت تغییر بدین:

if (distance <= closestDistance)
{
closestSegmentIndex = i;
closestDistance = distance;
list[0] = dataGridView1.Rows[i].Cells[0].Value;
list[1] = dataGridView1.Rows[i].Cells[1].Value;
...
...
list[23] = dataGridView1.Rows[i].Cells[23].Value;
if (distance < closestDistance) {
dt.Clear();
}
dt.Rows.Add(list);
}

حالا، تنها زمانی dt.Clear فراخوانی میشه که بالنی ای با فاصله نزدیکتر پیدا بشه.ولی در صورتی که بالن ها دقیقا در یک نقطه باشن، به dt اضافه میشن.

adineh67
جمعه 28 آذر 1393, 20:02 عصر
تغییراتو اعمال کردم ولی همون مشکل پیش اومد اگه به تصویری که گذاشتم توجه کنید تو تصویر بالایی دو تا بالن هست که رو محور Y ها قرار دارن وقتی رو بالن پایینی که به نقطه 0،0 نزدیکتره کلیک میکنم مشخصات قطعه مربوط به بالن بالایی رو هم نشون میده نمیدونم اینو چجوری حلش کنم :گیج:

plus
جمعه 28 آذر 1393, 20:26 عصر
طبیعتا نباید اینطوری بشه.اینجا:

if (distance < closestDistance) {
dt.Clear();
}

اگه بالن نزدیکتری پیدا بشه، آیتم های قبلی از dt حذف میشن.اگه منطق کد رو متوجه نشدین یکبار دیگه مطالبی که گفتم رو بخونید و بعد کد رو Debug کنید ببینید چرا اینطوری میشه.