ทำให้ preg_match_all หยุดหลังจากบันทึกการเปลี่ยนแปลงกลุ่ม

ฉันกำลังพยายามระบุความกว้างของสี่เหลี่ยมสีภายในรูปภาพ สำหรับการจัดการรูปภาพ ฉันใช้ Imagick สำหรับ PHP

แนวคิดคือการแปลงรูปภาพเป็น txt และค้นหา txt นี้ด้วย regex สำหรับพิกเซลทั้งหมดที่มีสีเฉพาะ (#00FF00)

นี่คือตัวอย่างลักษณะของ txt (ข้อความที่ตัดตอนมาจากคอลัมน์พิกเซล 0 แถว 83):

0,83: (255,255,255,1)  #FFFFFF  graya(255,1)
1,83: (255,255,255,1)  #FFFFFF  graya(255,1)
2,83: (255,255,255,1)  #FFFFFF  graya(255,1)
3,83: (0,255,0,1)  #00FF00  graya(0,1)
4,83: (0,255,0,1)  #00FF00  graya(0,1)
5,83: (0,255,0,1)  #00FF00  graya(0,1)
6,83: (255,255,255,1)  #FFFFFF  graya(255,1)
7,83: (255,255,255,1)  #FFFFFF  graya(255,1)
8,83: (255,255,255,1)  #FFFFFF  graya(255,1)
0,84: (255,255,255,1)  #FFFFFF  graya(255,1)
1,84: (255,255,255,1)  #FFFFFF  graya(255,1)
2,84: (255,255,255,1)  #FFFFFF  graya(255,1)
3,84: (0,255,0,1)  #00FF00  graya(0,1)
4,84: (0,255,0,1)  #00FF00  graya(0,1)
5,84: (0,255,0,1)  #00FF00  graya(0,1)
....

นี่คือรหัสของฉัน:

$canvasImg = new Imagick("_sources/passepartout/". $deviceName .".png");

$canvasImg->setFormat(txt);

preg_match_all("/(\\d+),(\\d+): \\(0,255,0,1\\)/is", $canvasImg, $colorMatchAll);

$firstPixelX = reset($colorMatch[1]);
$lastPixelX = end($colorMatch[1]);

$canvasWidth = $lastPixelX - $firstPixelX;

จนถึงตอนนี้วิธีนี้ใช้ได้ดี แต่มันช้ามากเมื่อพบพิกเซลทั้งหมดในสี่เหลี่ยมสี รวมถึงความสูงเต็มของแกน y

ตอนนี้เนื่องจากฉันสนใจเฉพาะความกว้างของสี่เหลี่ยม #00FF00 นี้ ฉันคิดว่าคงจะเร็วกว่านี้หาก regex พบพิกเซลแรกที่เป็น #00FF00 แล้วจึงผ่านแถวพิกเซลไปจนสุด (แถว 83 ในตัวอย่างของฉัน) และหยุดทันทีที่ถึงแถวที่ 84

มีการแก้ไขใดที่ฉันสามารถทำได้กับ regex ของฉันซึ่งทำในสิ่งที่ฉันกำลังมองหาหรือไม่


person micharuss    schedule 31.01.2016    source แหล่งที่มา
comment
จริงๆ แล้ว หากคุณต้องการความเร็วที่มากขึ้น ให้ใช้ฟังก์ชันการจัดการรูปภาพแทน.... สิ่งนี้   -  person Lucas Trzesniewski    schedule 31.01.2016
comment
ฉันเห็นว่าคุณสนใจแค่สิ่งสุดท้ายและอันดับแรก ?   -  person Yehia Awad    schedule 31.01.2016
comment
@ яшаใช่เพียงคนสุดท้ายและคนแรก   -  person micharuss    schedule 31.01.2016
comment
@LucasTrzesniewski ฉันพยายามแล้ว แต่ไม่พบสิ่งใดที่ตรงกับความต้องการของฉัน   -  person micharuss    schedule 31.01.2016
comment
php.net/manual/en/book.image.php   -  person Lucas Trzesniewski    schedule 31.01.2016
comment
ดังนั้นถ้าฉันเข้าใจคุณถูกต้องตลอดทั้งกระบวนการ คุณจะไม่ใช่จุดเริ่มต้นและจุดสิ้นสุดของแต่ละแถว ? ตัวอย่างเช่นสำหรับแถว 83 คุณต้องการจุดสุดท้ายและจุดสิ้นสุดสำหรับแถว 84 คุณต้องการจุดสุดท้ายและจุดสิ้นสุดและอื่นๆ ไปเรื่อยๆ หรือคุณต้องการเพียงจุดเริ่มต้นและจุดสิ้นสุดของข้อความทั้งหมด?   -  person Yehia Awad    schedule 31.01.2016
comment
@ яша ฉันต้องการเพียงแถวแรกและแถวสุดท้ายของสีนี้ปรากฏขึ้น แถวที่เหลือไม่สำคัญ แต่ฉันไม่รู้ว่าแถวแรกเริ่มจากตรงไหน โดยพื้นฐานแล้วให้หาแถวแรกที่มีสีนั้นแล้วดูว่าไปสิ้นสุดที่ใดในแถวนั้น แล้วหยุด   -  person micharuss    schedule 31.01.2016
comment
คุณมีเอาต์พุตนี้เป็นประเภทสตริงหรือไม่?   -  person Yehia Awad    schedule 31.01.2016
comment
@ яша คุณหมายถึงไฟล์ txt หรือไม่   -  person micharuss    schedule 31.01.2016
comment
ขั้นแรก: ทำตามที่ @LucasTrzesniewski พูด - ใช้ฟังก์ชั่นรูปภาพที่เหมาะสม อย่างไรก็ตาม คุณสามารถยึด regex ไว้ที่จุดเริ่มต้นได้ - วิธีแรกของคุณใช้เวลา 558 ขั้นตอน (อ้างอิงจาก regex101.com/r /pU7fL1/1) โดยมีจุดยึดอยู่ที่ 58 เท่านั้น ซึ่งเพิ่มขึ้น 90% (ดูที่นี่: regex101.com/r/pU7fL1/2)   -  person Jan    schedule 31.01.2016
comment
ขอบคุณทุกคน ฟังก์ชั่นรูปภาพน่าจะดีกว่านี้มาก แต่ดูเหมือนว่าจะไม่มีสิ่งใดที่สามารถตอบสนองสิ่งที่ฉันต้องการได้ แต่ฉันพบ regex ที่ทำสิ่งที่ฉันต้องการ: regex101.com/r/pU7fL1/3   -  person micharuss    schedule 01.02.2016
comment
@micharuss คุณกำลังทำปัญหาการบ้านแบบเดียวกับผู้ชายคนนี้หรือไม่: stackoverflow.com/questions/34939555/   -  person Danack    schedule 01.02.2016


คำตอบ (1)


คุณสามารถใช้ $imagick->trimImage() จากนั้น $imagick->getImagePage() เพื่อรับตำแหน่งหากสี่เหลี่ยมเป็นสิ่งเดียวบนภาพ หรือคุณสามารถวนซ้ำพิกเซลและทำการตรวจจับขอบของคุณเอง

$imagick = new \Imagick(realpath($imagePath));
$imageIterator = $imagick->getPixelRegionIterator(0, 0, 
     $imagick->getImageWidth(),
     $imagick->getImageHeight(),
 );

/* Loop through pixel rows */
foreach ($imageIterator as $pixels) {
    /** @var $pixel \ImagickPixel */
    /* Loop through the pixels in the row (columns) */
    foreach ($pixels as $column => $pixel) {
        $red = $pixel->getColorValue(\Imagick::COLOR_RED);
        $green = $pixel->getColorValue(\Imagick::COLOR_GREEN);
        $blue = $pixel->getColorValue(\Imagick::COLOR_BLUE);
        //Do detection here
    }
    /* Sync the iterator, this is important to do on each iteration */
    $imageIterator->syncIterator();
}

$imageIterator->clear();
person Danack    schedule 31.01.2016
comment
ขอบคุณ นั่นได้ผลสำหรับฉัน! น่าเสียดายที่ trimImage() ใช้งานไม่ได้เนื่องจากมีรูปภาพจำนวนมากนอกเหนือจากสี่เหลี่ยมสีของฉัน... - person micharuss; 01.02.2016