Here you go:
import bpy
import bmesh
from mathutils import Matrix, Vector
yuv = Matrix(((0.299, 0.587, 0.114),
(-0.14713, -0.28886, 0.436),
(0.615, -0.51499, -0.10001)))
class MESH_OT_select_similar_color(bpy.types.Operator):
"""Select faces based on diffuse color similarity"""
bl_idname = "mesh.select_similar_color"
bl_label = "Select Similar Color"
bl_options = {'REGISTER', 'UNDO'}
threshold = bpy.props.FloatProperty(name="Threshold", description="Use 0.0 to select faces with equal color only, larger values to select more dissimilarly colored faces too.", min=0.0, max=1.3271, subtype='FACTOR')
extend = bpy.props.BoolProperty(name="Extend", description="Extend the selection")
@classmethod
def poll(cls, context):
return (context.object is not None and
context.object.type == 'MESH' and
context.object.data.is_editmode)
def execute(self, context):
context.tool_settings.mesh_select_mode = (False, False, True)
ob = context.object
me = ob.data
bm = bmesh.from_edit_mesh(me)
mat_active = ob.active_material_index
mat_diffuse = {i: yuv * Vector(mat.diffuse_color) for i, mat in enumerate(me.materials)}
for face in bm.faces:
sel = (mat_diffuse[mat_active] - mat_diffuse[face.material_index]).length <= self.threshold
if not self.extend or (self.extend and sel):
face.select_set(sel)
bmesh.update_edit_mesh(me)
return {'FINISHED'}
def draw_func(self, context):
self.layout.operator(MESH_OT_select_similar_color.bl_idname, icon='COLOR')
def register():
bpy.utils.register_class(MESH_OT_select_similar_color)
bpy.types.MATERIAL_MT_specials.append(draw_func)
def unregister():
bpy.utils.unregister_class(MESH_OT_select_similar_color)
bpy.types.MATERIAL_MT_specials.remove(draw_func)
if __name__ == "__main__":
register()
It selects based on similarity (not sure how well it works for more complex cases). It adds an entry to the material specials menu. Threshold slider and extend option in the redo panel (3d view).