I have many objects similar to this and I import them into the scene using bpy.ops.import_scene.obj(filepath='model.obj', split_mode="OFF") to do some renderings using Blender's internal rendering engine. I want to loop over all of the materials and get the indices of the faces/polygons to which each of the materials have been applied to. However, I do not know how to do that. I initially tried to get the indices of the faces that use the same material_index as shown below:
matDict = {}
polys = bpy.context.scene.objects.active.data.polygons
mats = bpy.context.scene.objects.active.data.materials
for idx, poly in enumerate(polys):
if mats[poly.material_index].name not in matDict:
matDict[mats[poly.material_index].name] = []
matDict[mats[poly.material_index].name].append(idx)
else:
matDict[mats[poly.material_index].name].append(idx)
However this method does not give me back the list of all materials and misses most of the materials in mats and therefore, the number of keys in matDict is not equal to the number of materials. I'm not entirely sure why, but it could be because some of the materials are applied to the same faces and material_index returns only one of them. I wonder if someone can offer a better solution?

if ms.material is not NoneYou could usegeattr(mat, "name", "Not Assigned")in comp, or the material itself as a dic key, and have aNoneitem which will give you the non assigned material faces. (but not the index that is assigned) In that case could use(mat, mat_index)as the key. @Amir if you want to change blue to red you simply replace the material in the slots, eg where there's a blue material change it to red. you don't have to look at the faces at all. – batFINGER Mar 17 '18 at 12:14