ฉันเพิ่งจะนำสิ่งนี้ไปใช้ใน OpenGL ES 2.0 โดยใช้การตรวจจับมุมของแฮร์ริสและในขณะที่ฉันยังไม่เสร็จสมบูรณ์ ฉันได้ทำสิ่งนี้เป็นส่วนหนึ่งของกรอบงานโอเพ่นซอร์สบน iOSดังนั้นคุณสามารถตรวจสอบรหัสได้หากคุณสงสัยว่าขั้นตอนบางอย่างทำงานอย่างไร
- ลดภาพให้เป็นค่าความส่องสว่างโดยใช้ผลิตภัณฑ์จุดของค่า RGB ที่มีเวกเตอร์ (0.2125, 0.7154, 0.0721)
คำนวณอนุพันธ์ X และ Y โดยการลบค่าช่องสีแดงจากพิกเซลซ้ายและขวาและด้านบนและด้านล่างของพิกเซลปัจจุบัน จากนั้นฉันก็เก็บอนุพันธ์ x กำลังสองในช่องสีแดง, อนุพันธ์ Y กำลังสองในช่องสีเขียวและผลิตภัณฑ์ของอนุพันธ์ X และ Y ในช่องสีฟ้า ตัวแบ่งส่วนสำหรับสิ่งนี้มีลักษณะดังนี้:
precision highp float;
varying vec2 textureCoordinate;
varying vec2 leftTextureCoordinate;
varying vec2 rightTextureCoordinate;
varying vec2 topTextureCoordinate;
varying vec2 bottomTextureCoordinate;
uniform sampler2D inputImageTexture;
void main()
{
float topIntensity = texture2D(inputImageTexture, topTextureCoordinate).r;
float bottomIntensity = texture2D(inputImageTexture, bottomTextureCoordinate).r;
float leftIntensity = texture2D(inputImageTexture, leftTextureCoordinate).r;
float rightIntensity = texture2D(inputImageTexture, rightTextureCoordinate).r;
float verticalDerivative = abs(-topIntensity + bottomIntensity);
float horizontalDerivative = abs(-leftIntensity + rightIntensity);
gl_FragColor = vec4(horizontalDerivative * horizontalDerivative, verticalDerivative * verticalDerivative, verticalDerivative * horizontalDerivative, 1.0);
}
โดยที่ความแตกต่างเป็นเพียงพิกัดพื้นผิวออฟเซ็ตในแต่ละทิศทาง ฉันทำการคำนวณค่าล่วงหน้าเหล่านี้ใน Shader Vertex เพื่อกำจัดการอ่านค่าของพื้นผิวที่ขึ้นต่อกันซึ่งช้ามากใน GPU มือถือเหล่านี้
ใช้การเบลอแบบเกาส์กับภาพอนุพันธ์นี้ ฉันใช้การเบลอแนวนอนและแนวตั้งที่แยกจากกันและใช้ประโยชน์จากการกรองพื้นผิวของฮาร์ดแวร์เพื่อทำการเบลอที่ได้รับผลกระทบเก้าครั้งโดยมีเพียงห้าการอ่านพื้นผิวในแต่ละรอบ ผมอธิบาย Shader นี้ในคำตอบนี้กองมากเกิน
เรียกใช้การคำนวณการตรวจจับมุมแฮร์ริสที่แท้จริงโดยใช้ค่าอนุพันธ์ที่เบลอ ในกรณีนี้ฉันใช้การคำนวณที่อธิบายโดย Alison Noble ในปริญญาเอกของเธอ วิทยานิพนธ์ "คำอธิบายของภาพพื้นผิว" Shader ที่จัดการสิ่งนี้ดูเหมือนว่าต่อไปนี้:
varying highp vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
const mediump float harrisConstant = 0.04;
void main()
{
mediump vec3 derivativeElements = texture2D(inputImageTexture, textureCoordinate).rgb;
mediump float derivativeSum = derivativeElements.x + derivativeElements.y;
// This is the Noble variant on the Harris detector, from
// Alison Noble, "Descriptions of Image Surfaces", PhD thesis, Department of Engineering Science, Oxford University 1989, p45.
mediump float harrisIntensity = (derivativeElements.x * derivativeElements.y - (derivativeElements.z * derivativeElements.z)) / (derivativeSum);
// Original Harris detector
// highp float harrisIntensity = derivativeElements.x * derivativeElements.y - (derivativeElements.z * derivativeElements.z) - harrisConstant * derivativeSum * derivativeSum;
gl_FragColor = vec4(vec3(harrisIntensity * 10.0), 1.0);
}
ดำเนินการปราบปรามในพื้นที่ที่ไม่ใช่ค่าสูงสุดและใช้เกณฑ์เพื่อเน้นพิกเซลที่ผ่าน ฉันใช้ตัวแบ่งส่วนต่อไปนี้เพื่อสุ่มตัวอย่างแปดพิกเซลในละแวกของพิกเซลกลางและระบุว่าเป็นจำนวนสูงสุดในการจัดกลุ่มนั้นหรือไม่:
uniform sampler2D inputImageTexture;
varying highp vec2 textureCoordinate;
varying highp vec2 leftTextureCoordinate;
varying highp vec2 rightTextureCoordinate;
varying highp vec2 topTextureCoordinate;
varying highp vec2 topLeftTextureCoordinate;
varying highp vec2 topRightTextureCoordinate;
varying highp vec2 bottomTextureCoordinate;
varying highp vec2 bottomLeftTextureCoordinate;
varying highp vec2 bottomRightTextureCoordinate;
void main()
{
lowp float bottomColor = texture2D(inputImageTexture, bottomTextureCoordinate).r;
lowp float bottomLeftColor = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r;
lowp float bottomRightColor = texture2D(inputImageTexture, bottomRightTextureCoordinate).r;
lowp vec4 centerColor = texture2D(inputImageTexture, textureCoordinate);
lowp float leftColor = texture2D(inputImageTexture, leftTextureCoordinate).r;
lowp float rightColor = texture2D(inputImageTexture, rightTextureCoordinate).r;
lowp float topColor = texture2D(inputImageTexture, topTextureCoordinate).r;
lowp float topRightColor = texture2D(inputImageTexture, topRightTextureCoordinate).r;
lowp float topLeftColor = texture2D(inputImageTexture, topLeftTextureCoordinate).r;
// Use a tiebreaker for pixels to the left and immediately above this one
lowp float multiplier = 1.0 - step(centerColor.r, topColor);
multiplier = multiplier * 1.0 - step(centerColor.r, topLeftColor);
multiplier = multiplier * 1.0 - step(centerColor.r, leftColor);
multiplier = multiplier * 1.0 - step(centerColor.r, bottomLeftColor);
lowp float maxValue = max(centerColor.r, bottomColor);
maxValue = max(maxValue, bottomRightColor);
maxValue = max(maxValue, rightColor);
maxValue = max(maxValue, topRightColor);
gl_FragColor = vec4((centerColor.rgb * step(maxValue, centerColor.r) * multiplier), 1.0);
}
ด้วยการตั้งค่าขีด จำกัด ที่เหมาะสมสำหรับตัวกรองนี้มันสามารถระบุทั้ง 16 มุมในภาพนี้ได้แม้ว่ามันจะมีแนวโน้มที่จะวางมุมเป็นพิกเซลหรือดังนั้นภายในขอบที่แท้จริงของวัตถุ
บน iPhone 4 การตรวจจับมุมนี้สามารถเรียกใช้ที่ 20 FPS บนเฟรมวิดีโอ 640x480 ที่มาจากกล้องและ iPhone 4S สามารถประมวลผลวิดีโอขนาดนั้นที่ 60+ FPS ได้อย่างง่ายดาย นี่ควรจะเร็วกว่าการประมวลผลที่เชื่อมต่อกับ CPU สำหรับภารกิจเช่นนี้ถึงแม้ว่าตอนนี้กระบวนการอ่านกลับจุดจะถูกผูกกับ CPU และช้ากว่าที่ควรจะเป็น